import { Router, Request, Response, NextFunction } from 'express';
import multer from 'multer';
import { query, queryOne } from '../db';
import { moderateActionLimiter } from '../middleware/rateLimit';
import { importContacts } from '../services/csvImport';

const router = Router();
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } });

// GET /api/contacts
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const search = req.query.q as string;
    const limit = Math.min(parseInt(req.query.limit as string) || 50, 500);
    const offset = parseInt(req.query.offset as string) || 0;

    if (search) {
      const contacts = await query(
        `SELECT * FROM contacts
         WHERE email ILIKE $1 OR first_name ILIKE $1 OR last_name ILIKE $1
         ORDER BY created_at DESC LIMIT $2 OFFSET $3`,
        [`%${search}%`, limit, offset]
      );
      return res.json(contacts);
    }

    const contacts = await query(
      'SELECT * FROM contacts ORDER BY created_at DESC LIMIT $1 OFFSET $2',
      [limit, offset]
    );
    res.json(contacts);
  } catch (err) { next(err); }
});

// GET /api/contacts/:id
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const contact = await queryOne('SELECT * FROM contacts WHERE id=$1', [req.params.id]);
    if (!contact) return res.status(404).json({ error: 'Contact not found' });
    res.json(contact);
  } catch (err) { next(err); }
});

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

// POST /api/contacts — reject duplicates (409)
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { email, first_name, last_name, custom_fields, enrichment_data } = req.body;
    const normalized = String(email || '').toLowerCase().trim();
    if (!normalized) return res.status(400).json({ error: 'Email is required' });

    const existing = await queryOne('SELECT id FROM contacts WHERE email = $1', [normalized]);
    if (existing) return res.status(409).json({ error: 'A contact with this email already exists' });

    const contact = await queryOne(
      `INSERT INTO contacts (email, first_name, last_name, custom_fields, enrichment_data)
       VALUES ($1,$2,$3,$4,$5) RETURNING *`,
      [
        normalized,
        first_name || null,
        last_name || null,
        JSON.stringify(custom_fields || {}),
        JSON.stringify(enrichment_data && typeof enrichment_data === 'object' ? enrichment_data : {}),
      ]
    );
    res.status(201).json(contact);
  } catch (err) { next(err); }
});

// PATCH /api/contacts/:id
router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { email, first_name, last_name, custom_fields, enrichment_data, subscribed } = req.body;
    const cur = await queryOne<{ enrichment_data: Record<string, unknown> }>(
      'SELECT enrichment_data FROM contacts WHERE id=$1',
      [req.params.id]
    );
    if (!cur) return res.status(404).json({ error: 'Contact not found' });

    const enrichObj =
      enrichment_data !== undefined
        ? typeof enrichment_data === 'object' && enrichment_data !== null
          ? (enrichment_data as Record<string, unknown>)
          : {}
        : cur.enrichment_data || {};

    const contact = await queryOne(
      `UPDATE contacts SET email=$1, first_name=$2, last_name=$3,
       custom_fields=$4, enrichment_data=$5,
       subscribed = CASE WHEN $6::boolean IS NULL THEN subscribed ELSE $6::boolean END,
       updated_at=now()
       WHERE id=$7 RETURNING *`,
      [
        email,
        first_name || null,
        last_name || null,
        JSON.stringify(custom_fields || {}),
        JSON.stringify(enrichObj),
        subscribed === undefined ? null : !!subscribed,
        req.params.id,
      ]
    );
    res.json(contact);
  } catch (err) { next(err); }
});

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

// POST /api/contacts/import — CSV upload
router.post('/import', moderateActionLimiter, upload.single('file'), async (req: Request, res: Response, next: NextFunction) => {
  try {
    if (!req.file) return res.status(400).json({ error: 'No file uploaded' });
    const listId = req.body.list_id || undefined;
    const result = await importContacts(req.file.buffer, listId);
    res.json(result);
  } catch (err) { next(err); }
});

export default router;
