import { Router, Request, Response, NextFunction } from 'express';
import { query, queryOne } from '../db';
import { logger } from '../logger';
import { createTransporter } from '../mailer';
import { moderateActionLimiter } from '../middleware/rateLimit';
import { compileTemplate } from '../services/handlebars';

const router = Router();

// POST /api/transactional/send
router.post('/send', moderateActionLimiter, async (req: Request, res: Response, next: NextFunction) => {
  let recordId: string | undefined;
  try {
    const { to, subject, from_email, from_name, html, variables, template_id } = req.body;
    if (!to || !subject) {
      return res.status(400).json({ error: 'to and subject are required' });
    }

    let bodyHtml: string | undefined = typeof html === 'string' ? html : undefined;
    if (template_id) {
      const t = await queryOne<{ compiled_html: string | null }>(
        'SELECT compiled_html FROM templates WHERE id = $1',
        [template_id]
      );
      if (!t?.compiled_html) {
        return res.status(400).json({ error: 'template not found or has no compiled HTML' });
      }
      bodyHtml = t.compiled_html;
    }
    if (!bodyHtml) {
      return res.status(400).json({ error: 'html body or template_id is required' });
    }

    const compiledHtml = variables
      ? compileTemplate(bodyHtml, { email: to, unsubscribe_url: '#', ...variables })
      : bodyHtml;

    const record = await queryOne<{ id: string }>(
      `INSERT INTO transactional_emails (to_email, subject, from_email, html_body, status)
       VALUES ($1,$2,$3,$4,'queued') RETURNING id`,
      [to, subject, from_email || 'noreply@example.com', compiledHtml]
    );
    recordId = record?.id;

    const transporter = await createTransporter();
    await transporter.sendMail({
      from: from_name ? `"${from_name}" <${from_email}>` : from_email || 'noreply@example.com',
      to,
      subject,
      html: compiledHtml,
    });

    if (recordId) {
      await query(
        `UPDATE transactional_emails SET status='sent', sent_at=now() WHERE id=$1`,
        [recordId]
      );
    }

    res.json({ message: 'Email sent', id: recordId });
  } catch (err) {
    if (recordId) {
      try {
        await query(
          `UPDATE transactional_emails SET status='failed', metadata = $2 WHERE id=$1`,
          [recordId, JSON.stringify({ error: err instanceof Error ? err.message : String(err) })]
        );
      } catch (e) {
        logger.error(e, 'transactional failed status update');
      }
    }
    next(err);
  }
});

// GET /api/transactional — list recent
router.get('/', async (_req: Request, res: Response, next: NextFunction) => {
  try {
    const emails = await query(
      'SELECT id, to_email, subject, from_email, status, sent_at, created_at FROM transactional_emails ORDER BY created_at DESC LIMIT 100'
    );
    res.json(emails);
  } catch (err) { next(err); }
});

export default router;
