import { Router } from 'express';
import { requireAuth } from '../middleware/jwtAuth.js';

const router = Router({ mergeParams: true });

// GET /api/slides/:slideId/candidates
router.get('/', async (req, res) => {
  const pool = req.app.get('pool');
  const { slideId } = req.params;
  try {
    const result = await pool.query(
      'SELECT * FROM slide_candidates WHERE slide_id = $1 ORDER BY created_at',
      [slideId]
    );
    res.json({ candidates: result.rows });
  } catch (err) {
    console.error('Get candidates error:', err);
    res.status(500).json({ error: 'Failed to fetch candidates' });
  }
});

// POST /api/slides/:slideId/candidates
router.post('/', requireAuth, async (req, res) => {
  const pool = req.app.get('pool');
  const { slideId } = req.params;
  const { component_key, display_mode, props } = req.body;
  if (!component_key) return res.status(400).json({ error: 'component_key is required' });

  const proposed_by = req.user.sub;
  const proposed_by_name = req.user.name || req.user.email || req.user.sub;

  try {
    const result = await pool.query(
      `INSERT INTO slide_candidates
         (slide_id, component_key, display_mode, props, proposed_by, proposed_by_name)
       VALUES ($1, $2, $3, $4, $5, $6)
       RETURNING *`,
      [
        slideId, component_key, display_mode || null,
        props != null ? JSON.stringify(props) : null,
        proposed_by, proposed_by_name,
      ]
    );
    res.status(201).json({ candidate: result.rows[0] });
  } catch (err) {
    if (err.code === '23505') return res.status(409).json({ error: 'You already have a proposal for this slide' });
    if (err.code === '23503') return res.status(404).json({ error: 'Slide not found' });
    console.error('Create candidate error:', err);
    res.status(500).json({ error: 'Failed to create candidate' });
  }
});

// PUT /api/slides/:slideId/candidates/:candidateId
router.put('/:candidateId', requireAuth, async (req, res) => {
  const pool = req.app.get('pool');
  const { slideId, candidateId } = req.params;
  const { component_key, display_mode, props } = req.body;

  try {
    const existing = await pool.query(
      'SELECT * FROM slide_candidates WHERE id = $1 AND slide_id = $2',
      [candidateId, slideId]
    );
    if (existing.rows.length === 0) return res.status(404).json({ error: 'Candidate not found' });

    const c = existing.rows[0];
    const isOwner = c.proposed_by === req.user.sub;
    const isEditor = ['editor', 'admin'].includes(req.user.role);
    if (!isOwner && !isEditor) return res.status(403).json({ error: 'Forbidden' });

    const result = await pool.query(
      `UPDATE slide_candidates SET
         component_key = COALESCE($1, component_key),
         display_mode  = COALESCE($2, display_mode),
         props         = COALESCE($3, props),
         updated_at    = NOW()
       WHERE id = $4 RETURNING *`,
      [
        component_key || null,
        display_mode || null,
        props != null ? JSON.stringify(props) : null,
        candidateId,
      ]
    );
    res.json({ candidate: result.rows[0] });
  } catch (err) {
    console.error('Update candidate error:', err);
    res.status(500).json({ error: 'Failed to update candidate' });
  }
});

// DELETE /api/slides/:slideId/candidates/:candidateId
router.delete('/:candidateId', requireAuth, async (req, res) => {
  const pool = req.app.get('pool');
  const { slideId, candidateId } = req.params;

  try {
    const existing = await pool.query(
      'SELECT * FROM slide_candidates WHERE id = $1 AND slide_id = $2',
      [candidateId, slideId]
    );
    if (existing.rows.length === 0) return res.status(404).json({ error: 'Candidate not found' });

    const c = existing.rows[0];
    const isOwner = c.proposed_by === req.user.sub;
    const isEditor = ['editor', 'admin'].includes(req.user.role);
    if (!isOwner && !isEditor) return res.status(403).json({ error: 'Forbidden' });

    await pool.query('DELETE FROM slide_candidates WHERE id = $1', [candidateId]);
    res.json({ success: true });
  } catch (err) {
    console.error('Delete candidate error:', err);
    res.status(500).json({ error: 'Failed to delete candidate' });
  }
});

// POST /api/slides/:slideId/candidates/:candidateId/promote
router.post('/:candidateId/promote', requireAuth, async (req, res) => {
  const pool = req.app.get('pool');
  const { slideId, candidateId } = req.params;

  const isEditor = ['editor', 'admin'].includes(req.user.role);
  if (!isEditor) return res.status(403).json({ error: 'Editor or admin role required' });

  const client = await pool.connect();
  try {
    const existing = await client.query(
      'SELECT * FROM slide_candidates WHERE id = $1 AND slide_id = $2',
      [candidateId, slideId]
    );
    if (existing.rows.length === 0) return res.status(404).json({ error: 'Candidate not found' });

    const c = existing.rows[0];

    await client.query('BEGIN');

    const slideResult = await client.query(
      `UPDATE slides SET
         component_key = $1,
         display_mode  = COALESCE($2, display_mode),
         props         = COALESCE($3, props),
         updated_at    = NOW()
       WHERE id = $4 RETURNING *`,
      [c.component_key, c.display_mode, c.props, slideId]
    );

    await client.query('DELETE FROM slide_candidates WHERE id = $1', [candidateId]);

    await client.query('COMMIT');

    res.json({ slide: slideResult.rows[0] });
  } catch (err) {
    await client.query('ROLLBACK');
    console.error('Promote candidate error:', err);
    res.status(500).json({ error: 'Failed to promote candidate' });
  } finally {
    client.release();
  }
});

export default router;
