/**
 * @bobfrankston/mailx-api
 * Thin Express Router — delegates all logic to mailx-service.
 */

import { Router } from "express";
import { Store } from "@bobfrankston/mailx-store";
import { ImapManager } from "@bobfrankston/mailx-imap";
import { MailxService } from "@bobfrankston/mailx-service";
import { loadSettings } from "@bobfrankston/mailx-settings";

export function createApiRouter(store: Store, imapManager: ImapManager): Router {
    const svc = new MailxService(store, imapManager);
    const router = Router();
    router.use((req, res, next) => { res.type("json"); res.set("Cache-Control", "no-store"); next(); });

    // ── Accounts ──
    router.get("/accounts", (req, res) => { res.json(svc.getAccounts()); });

    // ── Folders ──
    // NB: getFolders/getUnifiedInbox/getMessages now return Promises (Phase 0
    // read-worker routes them off the main thread). Await before res.json or
    // the client gets a serialized empty Promise.
    router.get("/folders/:accountId", async (req, res) => { res.json(await svc.getFolders(req.params.accountId)); });

    // ── Messages ──
    router.get("/messages/unified/inbox", async (req, res) => {
        res.json(await svc.getUnifiedInbox(Number(req.query.page) || 1, Number(req.query.pageSize) || 50));
    });

    router.get("/messages/:accountId/:folderId", async (req, res) => {
        res.json(await svc.getMessages(
            req.params.accountId, Number(req.params.folderId),
            Number(req.query.page) || 1, Number(req.query.pageSize) || 50,
            (req.query.sort as string) || "date", (req.query.sortDir as string) || "desc",
            req.query.search as string
        ));
    });

    router.get("/message/:accountId/:uid", async (req, res) => {
        try {
            const msg = await svc.getMessage(
                req.params.accountId, Number(req.params.uid),
                req.query.allowRemote === "true",
                req.query.folderId ? Number(req.query.folderId) : undefined
            );
            res.json(msg);
        } catch (e: any) {
            res.status(e.message === "Message not found" ? 404 : 500).json({ error: e.message });
        }
    });

    router.patch("/message/:accountId/:uid/flags", async (req, res) => {
        try {
            await svc.updateFlags(req.params.accountId, Number(req.params.uid), req.body.flags);
            res.json({ ok: true });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Remote content allow-list ──
    router.post("/settings/allow-remote", (req, res) => {
        svc.allowRemoteContent(req.body.type, req.body.value);
        res.json({ ok: true });
    });

    // ── Search ──
    router.get("/search", async (req, res) => {
        try {
            const result = await svc.search(
                req.query.q as string || "", Number(req.query.page) || 1, Number(req.query.pageSize) || 50,
                req.query.scope as string || "all", req.query.accountId as string, Number(req.query.folderId) || 0
            );
            res.json(result);
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/search/rebuild", (req, res) => {
        res.json({ ok: true, indexed: svc.rebuildSearchIndex() });
    });

    // ── Sync ──
    router.get("/sync/pending", (req, res) => { res.json(svc.getSyncPending()); });

    router.post("/sync", async (req, res) => {
        try { await svc.syncAll(); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/sync/:accountId", async (req, res) => {
        try { await svc.syncAccount(req.params.accountId); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/reauth/:accountId", async (req, res) => {
        try {
            const ok = await svc.reauthenticate(req.params.accountId);
            res.json({ ok });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Autocomplete ──
    router.post("/autocomplete", async (req, res) => {
        try { res.json(await svc.autocomplete(req.body)); }
        catch (e: any) { res.status(500).json({ error: e.message, suggestion: "" }); }
    });

    router.get("/autocomplete/settings", (req, res) => {
        res.json(svc.getAutocompleteSettings());
    });

    router.post("/autocomplete/settings", (req, res) => {
        try { svc.saveAutocompleteSettings(req.body); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── First-time setup ──
    router.post("/setup", async (req, res) => {
        try {
            const { name, email, password } = req.body;
            const result = await svc.setupAccount(name, email, password);
            if (!result.ok) res.status(400);
            res.json(result);
        } catch (e: any) {
            res.status(500).json({ error: e.message });
        }
    });

    // ── Repair: restore accounts from DB cache to settings, re-register IMAP ──
    router.post("/repair-accounts", async (req, res) => {
        try {
            const result = await svc.repairAccounts();
            res.json(result);
        } catch (e: any) {
            res.status(500).json({ error: e.message });
        }
    });

    // ── Send ──
    router.post("/send", async (req, res) => {
        try { await svc.send(req.body); res.json({ ok: true, queued: true }); }
        catch (e: any) { console.error(`  Send error: ${e.message}`); res.status(500).json({ error: e.message }); }
    });

    // ── Bulk operations ──
    router.post("/messages/delete", async (req, res) => {
        try {
            const { accountId, uids } = req.body;
            await svc.deleteMessages(accountId, uids);
            res.json({ ok: true, count: uids.length });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/messages/move", async (req, res) => {
        try {
            const { accountId, uids, targetFolderId, targetAccountId, folderIds } = req.body;
            if (targetAccountId && targetAccountId !== accountId) {
                // Cross-account: must do one at a time
                for (const uid of uids) {
                    await svc.moveMessage(accountId, uid, targetFolderId, targetAccountId);
                }
            } else {
                await svc.moveMessages(accountId, uids, targetFolderId, folderIds);
            }
            res.json({ ok: true, count: uids.length });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/messages/spam", async (req, res) => {
        try {
            const { accountId, uids, folderIds } = req.body;
            const result = await svc.markAsSpamMessages(accountId, uids, folderIds);
            res.json({ ok: true, ...result });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Delete (single — kept for backward compat) ──
    router.delete("/message/:accountId/:uid", async (req, res) => {
        try { await svc.deleteMessage(req.params.accountId, Number(req.params.uid)); res.json({ ok: true }); }
        catch (e: any) {
            const status = e.message === "Message not found" ? 404 : 500;
            res.status(status).json({ error: e.message });
        }
    });

    // ── Move ──
    router.post("/message/:accountId/:uid/move", async (req, res) => {
        try {
            await svc.moveMessage(req.params.accountId, Number(req.params.uid), req.body.targetFolderId, req.body.targetAccountId);
            res.json({ ok: true });
        } catch (e: any) {
            const status = e.message === "Message not found" ? 404 : 500;
            res.status(status).json({ error: e.message });
        }
    });

    // ── Undelete ──
    router.post("/message/:accountId/:uid/undelete", async (req, res) => {
        try { await svc.undeleteMessage(req.params.accountId, Number(req.params.uid), req.body.folderId); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Direct IMAP delete ──
    router.delete("/imap/:accountId/:folderPath/:uid", async (req, res) => {
        try {
            await svc.deleteOnServer(req.params.accountId, decodeURIComponent(req.params.folderPath), Number(req.params.uid));
            res.json({ ok: true });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Folder management ──
    router.post("/folder/:accountId", async (req, res) => {
        try { await svc.createFolder(req.params.accountId, req.body.parentPath, req.body.name); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/folder/:accountId/:folderId/rename", async (req, res) => {
        try { await svc.renameFolder(req.params.accountId, Number(req.params.folderId), req.body.newName); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.delete("/folder/:accountId/:folderId", async (req, res) => {
        try { await svc.deleteFolder(req.params.accountId, Number(req.params.folderId)); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/folder/:accountId/:folderId/mark-read", async (req, res) => {
        try { svc.markFolderRead(Number(req.params.folderId)); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/folder/:accountId/:folderId/empty", async (req, res) => {
        try { await svc.emptyFolder(req.params.accountId, Number(req.params.folderId)); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Attachments ──
    router.get("/message/:accountId/:uid/attachment/:attachmentId", async (req, res) => {
        try {
            const att = await svc.getAttachment(
                req.params.accountId, Number(req.params.uid), Number(req.params.attachmentId),
                req.query.folderId ? Number(req.query.folderId) : undefined
            );
            res.set("Content-Type", att.contentType);
            res.set("Content-Disposition", `inline; filename="${att.filename}"`);
            res.send(att.content);
        } catch (e: any) {
            const status = e.message.includes("not found") || e.message.includes("not available") ? 404 : 500;
            res.status(status).json({ error: e.message });
        }
    });

    // ── Drafts ──
    router.post("/draft", async (req, res) => {
        try {
            const { accountId, subject, bodyHtml, bodyText, to, cc, previousDraftUid, draftId } = req.body;
            const result = await svc.saveDraft(accountId, subject, bodyHtml, bodyText, to, cc, previousDraftUid, draftId);
            res.json({ ok: true, draftUid: result.draftUid, draftId: result.draftId });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.delete("/draft", async (req, res) => {
        try {
            if (req.body.accountId && (req.body.draftUid || req.body.draftId)) await svc.deleteDraft(req.body.accountId, req.body.draftUid || 0, req.body.draftId);
            res.json({ ok: true });
        } catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    // ── Contacts ──
    router.get("/contacts", (req, res) => { res.json(svc.searchContacts(req.query.q as string || "")); });

    router.post("/contacts/sync-google", async (req, res) => {
        try { await svc.syncGoogleContacts(); res.json({ ok: true }); }
        catch (e: any) { res.status(500).json({ error: e.message }); }
    });

    router.post("/contacts/seed", async (req, res) => { res.json({ ok: true, added: await svc.seedContacts() }); });

    // ── Settings ──
    router.get("/settings", (req, res) => { res.json(svc.getSettings()); });
    router.put("/settings", (req, res) => { svc.saveSettings(req.body); res.json({ ok: true }); });

    return router;
}

// Re-export the service for direct use (Android bridge, worker thread, etc.)
export { MailxService } from "@bobfrankston/mailx-service";
