import { Request, Response } from 'express';
import db from '../../database/models/index.js';
import handlebars from 'handlebars';
import { registerEmailPartials, normalizeCtaPlaceholders } from '../../common/utils/handlebars-email.js';
import { sanitizeEmailTemplateBody, sanitizeEmailTemplateSubject } from '../../common/utils/email-template-sanitize.js';
import { isAllowedEmailTemplateCode } from '../../constants/allowed-email-template-codes.js';

const { EmailTemplate } = db;

const editableTemplateFields = ['templateCode', 'description', 'subject', 'body', 'placeholders', 'isActive'] as const;

function pickEditableTemplatePayload(body: Record<string, unknown>) {
    const out: Record<string, unknown> = {};
    for (const key of editableTemplateFields) {
        if (key in body) out[key] = body[key];
    }
    return out;
}

export const EmailTemplateController = {
    // Get all templates
    getAllTemplates: async (req: Request, res: Response) => {
        try {
            const templates = await EmailTemplate.findAll({
                order: [['templateCode', 'ASC']]
            });
            res.json({ success: true, data: templates });
        } catch (error) {
            console.error('Error fetching templates:', error);
            res.status(500).json({ success: false, message: 'Failed to fetch templates' });
        }
    },

    // Get single template
    getTemplate: async (req: Request, res: Response) => {
        try {
            const { id } = req.params;
            const template = await EmailTemplate.findByPk(id);

            if (!template) {
                return res.status(404).json({ success: false, message: 'Template not found' });
            }

            res.json({ success: true, data: template });
        } catch (error) {
            console.error('Error fetching template:', error);
            res.status(500).json({ success: false, message: 'Failed to fetch template' });
        }
    },

    // Create template
    createTemplate: async (req: Request, res: Response) => {
        try {
            const payload = pickEditableTemplatePayload(req.body as Record<string, unknown>);
            if (typeof payload.body === 'string') payload.body = sanitizeEmailTemplateBody(payload.body);
            if (typeof payload.subject === 'string') payload.subject = sanitizeEmailTemplateSubject(payload.subject);

            const rawCode = payload.templateCode;
            const normalized =
                typeof rawCode === 'string' ? rawCode.trim().toUpperCase() : '';
            if (!normalized || !isAllowedEmailTemplateCode(normalized)) {
                return res.status(400).json({
                    success: false,
                    message: 'templateCode must be one of the system-defined trigger codes.'
                });
            }
            payload.templateCode = normalized;

            const template = await EmailTemplate.create(payload);
            res.status(201).json({ success: true, data: template, message: 'Template created successfully' });
        } catch (error) {
            console.error('Error creating template:', error);
            res.status(500).json({ success: false, message: 'Failed to create template' });
        }
    },

    // Update template
    updateTemplate: async (req: Request, res: Response) => {
        try {
            const { id } = req.params;
            const existing = await EmailTemplate.findByPk(id);
            if (!existing) {
                return res.status(404).json({ success: false, message: 'Template not found' });
            }

            const payload = pickEditableTemplatePayload(req.body as Record<string, unknown>);
            if (typeof payload.body === 'string') payload.body = sanitizeEmailTemplateBody(payload.body);
            if (typeof payload.subject === 'string') payload.subject = sanitizeEmailTemplateSubject(payload.subject);

            if ('templateCode' in payload && payload.templateCode !== undefined) {
                const raw = payload.templateCode;
                const normalized =
                    typeof raw === 'string' ? raw.trim().toUpperCase() : '';
                const previous = existing.templateCode.trim().toUpperCase();
                if (normalized !== previous && !isAllowedEmailTemplateCode(normalized)) {
                    return res.status(400).json({
                        success: false,
                        message: 'templateCode must be one of the system-defined trigger codes.'
                    });
                }
                payload.templateCode = normalized;
            }

            const [updated] = await EmailTemplate.update(payload, {
                where: { id }
            });

            if (updated) {
                const updatedTemplate = await EmailTemplate.findByPk(id);
                res.json({ success: true, data: updatedTemplate, message: 'Template updated successfully' });
            } else {
                res.status(404).json({ success: false, message: 'Template not found' });
            }
        } catch (error) {
            console.error('Error updating template:', error);
            res.status(500).json({ success: false, message: 'Failed to update template' });
        }
    },

    // Delete template
    deleteTemplate: async (req: Request, res: Response) => {
        try {
            const { id } = req.params;
            const deleted = await EmailTemplate.destroy({
                where: { id }
            });

            if (deleted) {
                res.json({ success: true, message: 'Template deleted successfully' });
            } else {
                res.status(404).json({ success: false, message: 'Template not found' });
            }
        } catch (error) {
            console.error('Error deleting template:', error);
            res.status(500).json({ success: false, message: 'Failed to delete template' });
        }
    },

    // Preview template
    previewTemplate: async (req: Request, res: Response) => {
        try {
            const { subject, body, data } = req.body;

            if (!body) {
                return res.status(400).json({ success: false, message: 'Template body is required' });
            }

            // Compile content
            let compiledSubject = subject;
            let compiledBody = body;

            registerEmailPartials(handlebars);

            const safeBody = sanitizeEmailTemplateBody(body);
            const safeSubject = subject ? sanitizeEmailTemplateSubject(subject) : '';

            const safeData = normalizeCtaPlaceholders({
                ...(data || {}),
                year: new Date().getFullYear().toString()
            });

            try {
                const ensureHeaderFooter = (html: string) => {
                    const hasHeader = /class=["']header["']/i.test(html);
                    const hasFooter = /class=["']footer["']/i.test(html);
                    if (hasHeader && hasFooter) return html;
                    const wrapper = handlebars.compile(`{{> email_header}}\n{{{body}}}\n{{> email_footer}}`);
                    return wrapper({
                        ...safeData,
                        body: html
                    });
                };

                if (subject) {
                    const subjectTemplate = handlebars.compile(safeSubject);
                    compiledSubject = subjectTemplate(safeData);
                }

                const bodyTemplate = handlebars.compile(safeBody);
                compiledBody = ensureHeaderFooter(bodyTemplate(safeData));

                res.json({
                    success: true,
                    data: {
                        subject: compiledSubject,
                        html: compiledBody
                    }
                });
            } catch (compileError: any) {
                res.status(400).json({
                    success: false,
                    message: 'Template compilation failed',
                    error: compileError.message
                });
            }

        } catch (error) {
            console.error('Error previewing template:', error);
            res.status(500).json({ success: false, message: 'Failed to preview template' });
        }
    }
};
