import nodemailer from 'nodemailer';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import db from '../../database/models/index.js';
import handlebars from 'handlebars';
import { registerEmailPartials, normalizeCtaPlaceholders } from './handlebars-email.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Create test account (or use env vars in production)
let transporter: nodemailer.Transporter;
let transporterPromise: Promise<nodemailer.Transporter>;

const initTransporter = async () => {
    if (transporter) return transporter;
    if (transporterPromise) return transporterPromise;

    transporterPromise = nodemailer.createTestAccount().then((account) => {
        transporter = nodemailer.createTransport({
            host: account.smtp.host,
            port: account.smtp.port,
            secure: account.smtp.secure,
            auth: {
                user: account.user,
                pass: account.pass,
            },
        });
        console.log('[Email Service] Test account initialized:', account.user);
        return transporter;
    });

    return transporterPromise;
};

// Start initialization immediately
initTransporter().catch(err => console.error('Failed to initialize transporter:', err));

const { EmailTemplate } = db;

export const sendEmail = async (to: string, subject: string, templateCode: string, replacements: Record<string, string>) => {
    try {
        let finalHtml = '';
        let finalSubject = subject;
        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({
                ...replacements,
                year: new Date().getFullYear().toString(),
                body: html
            });
        };

        // Try fetching from DB first (Master Configuration)
        const dbTemplate = await EmailTemplate.findOne({ where: { templateCode, isActive: true } });

        if (dbTemplate) {
            registerEmailPartials(handlebars);

            const allReplacements = normalizeCtaPlaceholders({
                ...replacements,
                year: new Date().getFullYear().toString()
            });

            const subjectTemplate = handlebars.compile(dbTemplate.subject);
            finalSubject = subjectTemplate(allReplacements);

            const bodyTemplate = handlebars.compile(dbTemplate.body);
            finalHtml = ensureHeaderFooter(bodyTemplate(allReplacements));
        } else {
            registerEmailPartials(handlebars);
            const allReplacements = normalizeCtaPlaceholders({
                ...replacements,
                year: new Date().getFullYear().toString()
            });
            const templatesRoot = path.join(__dirname, '../../emailtemplates');
            const lowerFile = path.join(templatesRoot, `${templateCode.toLowerCase()}.html`);
            const exactFile = path.join(templatesRoot, `${templateCode}.html`);
            const templatePath = fs.existsSync(lowerFile)
                ? lowerFile
                : fs.existsSync(exactFile)
                  ? exactFile
                  : null;

            if (!templatePath) {
                throw new Error(`Template not found: ${templateCode}`);
            }

            const source = fs.readFileSync(templatePath, 'utf-8');
            const bodyTemplate = handlebars.compile(source);
            finalHtml = ensureHeaderFooter(bodyTemplate(allReplacements));
        }

        const readyTransporter = await initTransporter();
        if (!readyTransporter) {
            console.warn('Email transporter not initialized. Using fallback mock.');
            return;
        }

        const info = await readyTransporter.sendMail({
            from: '"Royal Enfield Onboarding" <no-reply@royalenfield.com>',
            to,
            subject: finalSubject,
            html: finalHtml
        });

        console.log(`[Email Service] Email sent to ${to}. MessageId: ${info.messageId}`);
        console.log(`[Email Service] Preview URL: ${nodemailer.getTestMessageUrl(info)}`);

        return info;
    } catch (error) {
        console.error(`Failed to send email (${templateCode}):`, error);
    }
};

export const sendOpportunityEmail = async (to: string, applicantName: string, location: string, applicationId: string) => {
    const link = `http://localhost:5173/questionnaire/${applicationId}`;
    await sendEmail(to, 'Action Required: Royal Enfield Dealership Opportunity', 'OPPORTUNITY', {
        applicantName,
        location,
        applicationId,
        link,
        ctaLabel: 'Complete Questionnaire'
    });
};

export const sendNonOpportunityEmail = async (to: string, applicantName: string, location: string) => {
    await sendEmail(to, 'Update on your Royal Enfield Dealership Application', 'NON_OPPORTUNITY', {
        applicantName,
        location
    });
};

export const sendInterviewScheduledEmail = async (to: string, name: string, applicationId: string, interview: any) => {
    const date = new Date(interview.scheduleDate);
    const time = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
    const formattedDate = date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
    const dateTime = `${formattedDate} ${time}`;

    await sendEmail(to, `Interview Scheduled: ${applicationId}`, 'INTERVIEW_SCHEDULED', {
        name,
        applicationId,
        level: interview.level,
        dateTime,
        type: interview.interviewType,
        location: interview.linkOrLocation,
        status: interview.status
    });
};

export const sendUserAssignedEmail = async (to: string, userName: string, applicationId: string, dealerName: string, participantType: string) => {
    await sendEmail(to, `New Application Assignment: ${applicationId}`, 'USER_ASSIGNED', {
        userName,
        applicationId,
        dealerName,
        participantType
    });
};

export const sendQuestionnaireAckEmail = async (to: string, applicantName: string, location: string, applicationId: string) => {
    await sendEmail(to, `Questionnaire Submitted Successfully: ${applicationId}`, 'QUESTIONNAIRE_SUBMITTED', {
        applicantName,
        location,
        applicationId
    });
};

export const sendShortlistedEmail = async (to: string, applicantName: string, location: string, applicationId: string) => {
    const portalLink = 'http://localhost:5173/login';
    await sendEmail(to, `Congratulations! You are Shortlisted: ${applicationId}`, 'APPLICANT_SHORTLISTED', {
        applicantName,
        location,
        applicationId,
        portalLink,
        ctaLabel: 'Visit Dealer Portal'
    });
};
