import { FastifyInstance } from "fastify"
import { ZAIClient, ZAI_MODELS, type ZAIConfig, type ZAIChatRequest, ZAIChatRequestSchema } from "../../integrations/zai-api"
import { Logger } from "../../logger"
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs"
import { join } from "path"
import { getUserIntegrationsDir } from "../../user-data"

interface ZAIRouteDeps {
    logger: Logger
}

const CONFIG_DIR = getUserIntegrationsDir()
const CONFIG_FILE = join(CONFIG_DIR, "zai-config.json")

export async function registerZAIRoutes(
    app: FastifyInstance,
    deps: ZAIRouteDeps
) {
    const logger = deps.logger.child({ component: "zai-routes" })

    // Ensure config directory exists
    if (!existsSync(CONFIG_DIR)) {
        mkdirSync(CONFIG_DIR, { recursive: true })
    }

    // Get Z.AI configuration
    app.get('/api/zai/config', async (request, reply) => {
        try {
            const config = getZAIConfig()
            return { config: { ...config, apiKey: config.apiKey ? '***' : undefined } }
        } catch (error) {
            logger.error({ error }, "Failed to get Z.AI config")
            return reply.status(500).send({ error: "Failed to get Z.AI configuration" })
        }
    })

    // Update Z.AI configuration
    app.post('/api/zai/config', async (request, reply) => {
        try {
            const { enabled, apiKey, endpoint } = request.body as Partial<ZAIConfig>
            updateZAIConfig({ enabled, apiKey, endpoint })
            logger.info("Z.AI configuration updated")
            return { success: true, config: { enabled, endpoint, apiKey: apiKey ? '***' : undefined } }
        } catch (error) {
            logger.error({ error }, "Failed to update Z.AI config")
            return reply.status(500).send({ error: "Failed to update Z.AI configuration" })
        }
    })

    // Test Z.AI connection
    app.post('/api/zai/test', async (request, reply) => {
        try {
            const config = getZAIConfig()
            if (!config.enabled) {
                return reply.status(400).send({ error: "Z.AI is not enabled" })
            }

            const client = new ZAIClient(config)
            const isConnected = await client.testConnection()

            return { connected: isConnected }
        } catch (error) {
            logger.error({ error }, "Z.AI connection test failed")
            return reply.status(500).send({ error: "Connection test failed" })
        }
    })

    // List available models
    app.get('/api/zai/models', async (request, reply) => {
        try {
            return { models: ZAI_MODELS.map(name => ({ name, provider: "zai" })) }
        } catch (error) {
            logger.error({ error }, "Failed to list Z.AI models")
            return reply.status(500).send({ error: "Failed to list models" })
        }
    })

    // Chat completion endpoint
    app.post('/api/zai/chat', async (request, reply) => {
        try {
            const config = getZAIConfig()
            if (!config.enabled) {
                return reply.status(400).send({ error: "Z.AI is not enabled" })
            }

            const client = new ZAIClient(config)
            const chatRequest = request.body as ZAIChatRequest

            // Handle streaming
            if (chatRequest.stream) {
                reply.raw.writeHead(200, {
                    'Content-Type': 'text/event-stream',
                    'Cache-Control': 'no-cache',
                    'Connection': 'keep-alive',
                })

                try {
                    for await (const chunk of client.chatStream(chatRequest)) {
                        reply.raw.write(`data: ${JSON.stringify(chunk)}\n\n`)

                        // Check for finish_reason to end stream
                        const finishReason = chunk.choices[0]?.finish_reason
                        if (finishReason) {
                            reply.raw.write('data: [DONE]\n\n')
                            break
                        }
                    }

                    reply.raw.end()
                } catch (streamError) {
                    logger.error({ error: streamError }, "Z.AI streaming failed")
                    reply.raw.write(`data: ${JSON.stringify({ error: String(streamError) })}\n\n`)
                    reply.raw.end()
                }
            } else {
                const response = await client.chat(chatRequest)
                return response
            }
        } catch (error) {
            logger.error({ error }, "Z.AI chat request failed")
            return reply.status(500).send({ error: "Chat request failed" })
        }
    })

    logger.info("Z.AI routes registered")
}

function getZAIConfig(): ZAIConfig {
    try {
        if (existsSync(CONFIG_FILE)) {
            const data = readFileSync(CONFIG_FILE, 'utf-8')
            return JSON.parse(data)
        }
        return { enabled: false, endpoint: "https://api.z.ai/api/paas/v4", timeout: 300000 }
    } catch {
        return { enabled: false, endpoint: "https://api.z.ai/api/paas/v4", timeout: 300000 }
    }
}

function updateZAIConfig(config: Partial<ZAIConfig>): void {
    const current = getZAIConfig()
    const updated = { ...current, ...config }
    writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2))
}
