import { Router, Request, Response, NextFunction } from 'express';
import { query, queryOne } from '../db';
import { logger } from '../logger';
import { moderateActionLimiter, strictActionLimiter } from '../middleware/rateLimit';
import { sendCampaign, sendTestEmail } from '../services/campaignSender';

const router = Router();

// GET /api/campaigns
router.get('/', async (_req: Request, res: Response, next: NextFunction) => {
  try {
    const campaigns = await query(`
      SELECT c.*, cs.total_recipients, cs.sent_count, cs.open_count,
             cs.click_count, cs.bounce_count, cs.open_rate, cs.click_rate,
             l.name as list_name, t.name as template_name
      FROM campaigns c
      LEFT JOIN campaign_stats cs ON cs.campaign_id = c.id
      LEFT JOIN lists l ON l.id = c.list_id
      LEFT JOIN templates t ON t.id = c.template_id
      ORDER BY c.created_at DESC
    `);
    res.json(campaigns);
  } catch (err) { next(err); }
});

// GET /api/campaigns/:id
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const campaign = await queryOne(`
      SELECT c.*, cs.total_recipients, cs.sent_count, cs.open_count,
             cs.click_count, cs.bounce_count, cs.unsubscribe_count, cs.open_rate, cs.click_rate,
             l.name as list_name, t.name as template_name, t.compiled_html
      FROM campaigns c
      LEFT JOIN campaign_stats cs ON cs.campaign_id = c.id
      LEFT JOIN lists l ON l.id = c.list_id
      LEFT JOIN templates t ON t.id = c.template_id
      WHERE c.id = $1
    `, [req.params.id]);
    if (!campaign) return res.status(404).json({ error: 'Campaign not found' });
    res.json(campaign);
  } catch (err) { next(err); }
});

// POST /api/campaigns
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { name, subject, from_name, from_email, reply_to, list_id, template_id } = req.body;
    const campaign = await queryOne(
      `INSERT INTO campaigns (name, subject, from_name, from_email, reply_to, list_id, template_id)
       VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING *`,
      [name, subject, from_name, from_email, reply_to || null, list_id || null, template_id || null]
    );
    res.status(201).json(campaign);
  } catch (err) { next(err); }
});

// PATCH /api/campaigns/:id
router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { name, subject, from_name, from_email, reply_to, list_id, template_id, scheduled_at } = req.body;
    const campaign = await queryOne(
      `UPDATE campaigns
       SET name=$1, subject=$2, from_name=$3, from_email=$4, reply_to=$5,
           list_id=$6, template_id=$7, scheduled_at=$8, updated_at=now()
       WHERE id=$9 AND status IN ('draft','scheduled','failed')
       RETURNING *`,
      [name, subject, from_name, from_email, reply_to || null, list_id || null, template_id || null, scheduled_at || null, req.params.id]
    );
    if (!campaign) return res.status(404).json({ error: 'Campaign not found or not editable' });
    res.json(campaign);
  } catch (err) { next(err); }
});

// DELETE /api/campaigns/:id
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    await query(`DELETE FROM campaigns WHERE id=$1 AND status='draft'`, [req.params.id]);
    res.status(204).send();
  } catch (err) { next(err); }
});

// POST /api/campaigns/:id/send
router.post('/:id/send', strictActionLimiter, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const campaign = await queryOne<{ status: string }>(
      'SELECT status FROM campaigns WHERE id=$1', [req.params.id]
    );
    if (!campaign) return res.status(404).json({ error: 'Campaign not found' });
    if (!['draft', 'scheduled', 'paused', 'failed'].includes(campaign.status)) {
      return res.status(400).json({ error: `Cannot send campaign with status: ${campaign.status}` });
    }

    // Kick off async — don't await
    sendCampaign(req.params.id).catch(err => {
      logger.error({ err, campaignId: req.params.id }, 'Campaign send failed');
      query(`UPDATE campaigns SET status='paused', updated_at=now() WHERE id=$1`, [req.params.id]);
    });

    res.json({ message: 'Campaign send initiated' });
  } catch (err) { next(err); }
});

// POST /api/campaigns/:id/test
router.post('/:id/test', moderateActionLimiter, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { email } = req.body;
    if (!email) return res.status(400).json({ error: 'email is required' });
    await sendTestEmail(req.params.id, email);
    res.json({ message: `Test email sent to ${email}` });
  } catch (err) { next(err); }
});

// GET /api/campaigns/:id/recipients
router.get('/:id/recipients', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const recipients = await query(`
      SELECT cr.id, cr.status, cr.track_token, cr.sent_at, cr.opened_at, cr.clicked_at,
             c.email, c.first_name, c.last_name
      FROM campaign_recipients cr
      JOIN contacts c ON c.id = cr.contact_id
      WHERE cr.campaign_id = $1
      ORDER BY cr.sent_at DESC NULLS LAST
      LIMIT 500
    `, [req.params.id]);
    res.json(recipients);
  } catch (err) { next(err); }
});

export default router;
