// modules/helpdesk/helpdesk.routes.ts
import { FastifyPluginAsync } from 'fastify'
import { createConversation, getConversations, updateConversationStatus } from '../modules/helpdesk/helpdesk.conversation.service.js'
import { addMessage, getMessages } from '../modules/helpdesk/helpdesk.message.service.js'
import { getOrCreateContact } from '../modules/helpdesk/helpdesk.contact.service.js'
import {decrypt, encrypt} from "../utils/crypt";
import nodemailer from "nodemailer"
import { eq } from "drizzle-orm";
import {
    helpdesk_channel_instances,
    helpdesk_contacts,
    helpdesk_conversations,
    helpdesk_messages,
} from "../../db/schema";

const helpdeskRoutes: FastifyPluginAsync = async (server) => {
    // 📩 1. Liste aller Konversationen
    server.get('/helpdesk/conversations', async (req, res) => {
        const tenant_id = req.user?.tenant_id
        if (!tenant_id) return res.status(401).send({ error: 'Unauthorized' })

        const { status } = req.query as {status: string}
        const conversations = await getConversations(server, tenant_id, { status })
        return res.send(conversations)
    })

    // 🆕 2. Neue Konversation erstellen
    server.post('/helpdesk/conversations', async (req, res) => {
        const tenant_id = req.user?.tenant_id
        if (!tenant_id) return res.status(401).send({ error: 'Unauthorized' })

        const { contact, channel_instance_id, subject, message } = req.body as {
            contact: object
            channel_instance_id: string
            subject: string
            message: string
        }
        if (!contact || !channel_instance_id) {
            return res.status(400).send({ error: 'Missing contact or channel_instance_id' })
        }

        // 1. Konversation erstellen
        const conversation = await createConversation(server, {
            tenant_id,
            contact,
            channel_instance_id,
            subject,
        })

        // 2. Falls erste Nachricht vorhanden → hinzufügen
        if (message) {
            await addMessage(server, {
                tenant_id,
                conversation_id: conversation.id,
                direction: 'incoming',
                payload: { type: 'text', text: message },
            })
        }

        return res.status(201).send(conversation)
    })

    // 🧭 3. Einzelne Konversation abrufen
    server.get('/helpdesk/conversations/:id', async (req, res) => {
        const tenant_id = req.user?.tenant_id
        const {id: conversation_id} = req.params as {id: string}

        const rows = await server.db
            .select({
                conversation: helpdesk_conversations,
                contact: helpdesk_contacts
            })
            .from(helpdesk_conversations)
            .leftJoin(helpdesk_contacts, eq(helpdesk_contacts.id, helpdesk_conversations.contactId))
            .where(eq(helpdesk_conversations.id, conversation_id))

        const data = rows[0]
        if (!data || data.conversation.tenantId !== tenant_id) return res.status(404).send({ error: 'Conversation not found' })

        return res.send({
            ...data.conversation,
            channel_instance_id: data.conversation.channelInstanceId,
            contact_id: data.conversation.contactId,
            contact_person_id: data.conversation.contactPersonId,
            created_at: data.conversation.createdAt,
            customer_id: data.conversation.customerId,
            last_message_at: data.conversation.lastMessageAt,
            tenant_id: data.conversation.tenantId,
            ticket_number: data.conversation.ticketNumber,
            helpdesk_contacts: data.contact,
        })
    })

    // 🔄 4. Konversation Status ändern
    server.patch('/helpdesk/conversations/:id/status', async (req, res) => {
        const {id: conversation_id} = req.params as { id: string }
        const { status } = req.body as { status: string }

        const updated = await updateConversationStatus(server, conversation_id, status)
        return res.send(updated)
    })

    // 💬 5. Nachrichten abrufen
    server.get('/helpdesk/conversations/:id/messages', async (req, res) => {
        const {id:conversation_id} = req.params as { id: string }
        const messages = await getMessages(server, conversation_id)
        return res.send(messages)
    })

    // 💌 6. Nachricht hinzufügen (z. B. Antwort eines Agents)
    server.post('/helpdesk/conversations/:id/messages', async (req, res) => {
        console.log(req.user)
        const tenant_id = req.user?.tenant_id
        const author_user_id = req.user?.user_id
        const {id: conversation_id} = req.params as { id: string }
        const { text } = req.body as { text: string }

        if (!text) return res.status(400).send({ error: 'Missing message text' })

        const message = await addMessage(server, {
            tenant_id,
            conversation_id,
            author_user_id,
            direction: 'outgoing',
            payload: { type: 'text', text },
        })

        return res.status(201).send(message)
    })

    // 👤 7. Kontakt suchen oder anlegen
    server.post('/helpdesk/contacts', async (req, res) => {
        const tenant_id = req.user?.tenant_id
        const { email, phone, display_name } = req.body as { email: string; phone: string, display_name: string }

        const contact = await getOrCreateContact(server, tenant_id, { email, phone, display_name })
        return res.status(201).send(contact)
    })

    server.post("/helpdesk/channels", {
        schema: {
            body: {
                type: "object",
                required: ["type_id", "name", "config"],
                properties: {
                    type_id: { type: "string" },
                    name: { type: "string" },
                    config: { type: "object" },
                    is_active: { type: "boolean", default: true },
                },
            },
        },
        handler: async (req, reply) => {
            const {  type_id, name, config, is_active = true } = req.body as
                {
                    type_id: string,
                    name: string,
                    config: {
                        imap:{
                            host: string | object,
                            user: string | object,
                            pass: string | object,
                        },
                        smtp:{
                            host: string | object,
                            user: string | object,
                            pass: string | object,
                        }
                    },
                    is_active: boolean
                }

            // 🔒 Tenant aus Auth-Context
            const tenant_id = req.user?.tenant_id
            if (!tenant_id) {
                return reply.status(401).send({ error: "Kein Tenant im Benutzerkontext gefunden." })
            }

            if (type_id !== "email") {
                return reply.status(400).send({ error: "Nur Typ 'email' wird aktuell unterstützt." })
            }

            try {
                const safeConfig = { ...config }

                // 🔐 IMAP-Daten verschlüsseln
                if (safeConfig.imap) {
                    if (safeConfig.imap.host)
                        safeConfig.imap.host = encrypt(safeConfig.imap.host)
                    if (safeConfig.imap.user)
                        safeConfig.imap.user = encrypt(safeConfig.imap.user)
                    if (safeConfig.imap.pass)
                        safeConfig.imap.pass = encrypt(safeConfig.imap.pass)
                }

                // 🔐 SMTP-Daten verschlüsseln
                if (safeConfig.smtp) {
                    if (safeConfig.smtp.host)
                        safeConfig.smtp.host = encrypt(safeConfig.smtp.host)
                    if (safeConfig.smtp.user)
                        safeConfig.smtp.user = encrypt(safeConfig.smtp.user)
                    if (safeConfig.smtp.pass)
                        safeConfig.smtp.pass = encrypt(safeConfig.smtp.pass)
                }

                const inserted = await server.db
                    .insert(helpdesk_channel_instances)
                    .values({
                        tenantId: tenant_id,
                        typeId: type_id,
                        name,
                        config: safeConfig,
                        isActive: is_active,
                    })
                    .returning()

                const data = inserted[0]
                if (!data) throw new Error("Konnte Channel nicht erstellen")
                const responseConfig: any = data.config

                // sensible Felder aus Response entfernen
                if (responseConfig?.imap) {
                    delete responseConfig.imap.host
                    delete responseConfig.imap.user
                    delete responseConfig.imap.pass
                }
                if (responseConfig?.smtp) {
                    delete responseConfig.smtp.host
                    delete responseConfig.smtp.user
                    delete responseConfig.smtp.pass
                }

                reply.send({
                    message: "E-Mail-Channel erfolgreich erstellt",
                    channel: {
                        ...data,
                        config: responseConfig
                    },
                })
            } catch (err) {
                console.error("Fehler bei Channel-Erstellung:", err)
                reply.status(500).send({ error: err.message })
            }
        },
    })

    server.post("/helpdesk/conversations/:id/reply", {
        schema: {
            body: {
                type: "object",
                required: ["text"],
                properties: {
                    text: { type: "string" },
                },
            },
        },
        handler: async (req, reply) => {
            const conversationId = (req.params as any).id
            const { text } = req.body as { text: string }

            // 🔹 Konversation inkl. Channel + Kontakt laden
            const rows = await server.db
                .select({
                    conversation: helpdesk_conversations,
                    contact: helpdesk_contacts,
                    channel: helpdesk_channel_instances,
                })
                .from(helpdesk_conversations)
                .leftJoin(helpdesk_contacts, eq(helpdesk_contacts.id, helpdesk_conversations.contactId))
                .leftJoin(helpdesk_channel_instances, eq(helpdesk_channel_instances.id, helpdesk_conversations.channelInstanceId))
                .where(eq(helpdesk_conversations.id, conversationId))
                .limit(1)

            const conv = rows[0]

            console.log(conv)

            if (!conv) {
                reply.status(404).send({ error: "Konversation nicht gefunden" })
                return
            }

            const contact = conv.contact as unknown as {email: string}
            const channel = conv.channel as unknown as {name: string, config: any}

            console.log(contact)
            if (!contact?.email) {
                reply.status(400).send({ error: "Kein Empfänger gefunden" })
                return
            }

            // 🔐 SMTP-Daten entschlüsseln
            try {
                // @ts-ignore
                const smtp = channel?.config?.smtp
                const host =
                    typeof smtp.host === "object" ? decrypt(smtp.host) : smtp.host
                const user =
                    typeof smtp.user === "object" ? decrypt(smtp.user) : smtp.user
                const pass =
                    typeof smtp.pass === "object" ? decrypt(smtp.pass) : smtp.pass

                // 🔧 Transporter
                const transporter = nodemailer.createTransport({
                    host,
                    port: smtp.port || 465,
                    secure: smtp.secure ?? true,
                    auth: { user, pass },
                })

                // 📩 Mail senden

                const mailOptions = {
                    from: `"${channel?.name}" <${user}>`,
                    to: contact.email,
                    subject: `${conv.conversation.ticketNumber} | ${conv.conversation.subject}` || `${conv.conversation.ticketNumber} | Antwort vom FEDEO Helpdesk`,
                    text,
                }

                const info = await transporter.sendMail(mailOptions)
                console.log(`[Helpdesk SMTP] Gesendet an ${contact.email}: ${info.messageId}`)

                // 💾 Nachricht speichern
                await server.db
                    .insert(helpdesk_messages)
                    .values({
                        tenantId: conv.conversation.tenantId,
                        conversationId: conversationId,
                        direction: "outgoing",
                        payload: { type: "text", text },
                        externalMessageId: info.messageId,
                        receivedAt: new Date(),
                    })

                // 🔁 Konversation aktualisieren
                await server.db
                    .update(helpdesk_conversations)
                    .set({ lastMessageAt: new Date() })
                    .where(eq(helpdesk_conversations.id, conversationId))

                reply.send({
                    message: "E-Mail erfolgreich gesendet",
                    messageId: info.messageId,
                })
            } catch (err: any) {
                console.error("Fehler beim SMTP-Versand:", err)
                reply.status(500).send({ error: err.message })
            }
        },
    })

}

export default helpdeskRoutes
