import nodemailer from "nodemailer"
import { FastifyInstance } from "fastify"
import { eq } from "drizzle-orm"

import { sendMailAsUser } from "../utils/emailengine"
import { encrypt, decrypt } from "../utils/crypt"
import { userCredentials } from "../../db/schema"
// Pfad ggf. anpassen

// @ts-ignore
import MailComposer from "nodemailer/lib/mail-composer/index.js"
import { ImapFlow } from "imapflow"

export default async function emailAsUserRoutes(server: FastifyInstance) {


    // ======================================================================
    // CREATE OR UPDATE EMAIL ACCOUNT
    // ======================================================================
    server.post("/email/accounts/:id?", async (req, reply) => {
        try {
            if (!req.user?.tenant_id) {
                return reply.code(400).send({ error: "No tenant selected" })
            }

            const { id } = req.params as { id?: string }

            const body = req.body as {
                email: string
                password: string
                smtp_host: string
                smtp_port: number
                smtp_ssl: boolean
                imap_host: string
                imap_port: number
                imap_ssl: boolean
            }

            // -----------------------------
            // UPDATE EXISTING
            // -----------------------------
            if (id) {
                const saveData = {
                    emailEncrypted: body.email ? encrypt(body.email) : undefined,
                    passwordEncrypted: body.password ? encrypt(body.password) : undefined,
                    smtpHostEncrypted: body.smtp_host ? encrypt(body.smtp_host) : undefined,
                    smtpPort: body.smtp_port,
                    smtpSsl: body.smtp_ssl,
                    imapHostEncrypted: body.imap_host ? encrypt(body.imap_host) : undefined,
                    imapPort: body.imap_port,
                    imapSsl: body.imap_ssl,
                }

                await server.db
                    .update(userCredentials)
                    //@ts-ignore
                    .set(saveData)
                    .where(eq(userCredentials.id, id))

                return reply.send({ success: true })
            }

            // -----------------------------
            // CREATE NEW
            // -----------------------------
            const insertData = {
                userId: req.user.user_id,
                tenantId: req.user.tenant_id,
                type: "mail",

                emailEncrypted: encrypt(body.email),
                passwordEncrypted: encrypt(body.password),

                smtpHostEncrypted: encrypt(body.smtp_host),
                smtpPort: body.smtp_port,
                smtpSsl: body.smtp_ssl,

                imapHostEncrypted: encrypt(body.imap_host),
                imapPort: body.imap_port,
                imapSsl: body.imap_ssl,
            }

            //@ts-ignore
            await server.db.insert(userCredentials).values(insertData)

            return reply.send({ success: true })
        } catch (err) {
            console.error("POST /email/accounts error:", err)
            return reply.code(500).send({ error: "Internal Server Error" })
        }
    })



    // ======================================================================
    // GET SINGLE OR ALL ACCOUNTS
    // ======================================================================
    server.get("/email/accounts/:id?", async (req, reply) => {
        try {
            if (!req.user?.tenant_id) {
                return reply.code(400).send({ error: "No tenant selected" })
            }

            const { id } = req.params as { id?: string }

            // ============================================================
            // LOAD SINGLE ACCOUNT
            // ============================================================
            if (id) {
                const rows = await server.db
                    .select()
                    .from(userCredentials)
                    .where(eq(userCredentials.id, id))

                const row = rows[0]
                if (!row) return reply.code(404).send({ error: "Not found" })

                const returnData: any = {}

                Object.entries(row).forEach(([key, val]) => {
                    if (key.endsWith("Encrypted")) {
                        const cleanKey = key.replace("Encrypted", "")
                        // @ts-ignore
                        returnData[cleanKey] = decrypt(val as string)
                    } else {
                        returnData[key] = val
                    }
                })

                return reply.send(returnData)
            }

            // ============================================================
            // LOAD ALL ACCOUNTS FOR TENANT
            // ============================================================
            const rows = await server.db
                .select()
                .from(userCredentials)
                .where(eq(userCredentials.tenantId, req.user.tenant_id))

            const accounts = rows.map(row => {
                const temp: any = {}
                console.log(row)
                Object.entries(row).forEach(([key, val]) => {
                    console.log(key,val)
                    if (key.endsWith("Encrypted") && val) {
                        // @ts-ignore
                        temp[key.replace("Encrypted", "")] = decrypt(val)
                    } else {
                        temp[key] = val
                    }
                })
                return temp
            })

            return reply.send(accounts)

        } catch (err) {
            console.error("GET /email/accounts error:", err)
            return reply.code(500).send({ error: "Internal Server Error" })
        }
    })



    // ======================================================================
    // SEND EMAIL + SAVE IN IMAP SENT FOLDER
    // ======================================================================
    server.post("/email/send", async (req, reply) => {
        try {
            const body = req.body as {
                to: string
                cc?: string
                bcc?: string
                subject?: string
                text?: string
                html?: string
                attachments?: any
                account: string
            }

            // Fetch email credentials
            const rows = await server.db
                .select()
                .from(userCredentials)
                .where(eq(userCredentials.id, body.account))

            const row = rows[0]
            if (!row) return reply.code(404).send({ error: "Account not found" })

            const accountData: any = {}

            Object.entries(row).forEach(([key, val]) => {
                if (key.endsWith("Encrypted") && val) {
                    // @ts-ignore
                    accountData[key.replace("Encrypted", "")] = decrypt(val as string)
                } else {
                    accountData[key] = val
                }
            })

            // -------------------------
            // SEND EMAIL VIA SMTP
            // -------------------------
            const transporter = nodemailer.createTransport({
                host: accountData.smtpHost,
                port: accountData.smtpPort,
                secure: accountData.smtpSsl,
                auth: {
                    user: accountData.email,
                    pass: accountData.password,
                },
            })

            const message = {
                from: accountData.email,
                to: body.to,
                cc: body.cc,
                bcc: body.bcc,
                subject: body.subject,
                html: body.html,
                text: body.text,
                attachments: body.attachments,
            }

            const info = await transporter.sendMail(message)

            // -------------------------
            // SAVE TO IMAP SENT FOLDER
            // -------------------------
            const imap = new ImapFlow({
                host: accountData.imapHost,
                port: accountData.imapPort,
                secure: accountData.imapSsl,
                auth: {
                    user: accountData.email,
                    pass: accountData.password,
                },
            })

            await imap.connect()

            const mail = new MailComposer(message)
            const raw = await mail.compile().build()

            for await (const mailbox of await imap.list()) {
                if (mailbox.specialUse === "\\Sent") {
                    await imap.mailboxOpen(mailbox.path)
                    await imap.append(mailbox.path, raw, ["\\Seen"])
                    await imap.logout()
                }
            }

            return reply.send({ success: true })

        } catch (err) {
            console.error("POST /email/send error:", err)
            return reply.code(500).send({ error: "Failed to send email" })
        }
    })

}
