// routes/archerTickets.js
const express = require('express');
const pool = require('../db');
const { requireAuth, requireGroup } = require('../middleware/auth');
const logAudit = require('../helpers/auditLog');

// Validation helpers
const CVE_ID_PATTERN = /^CVE-\d{4}-\d{4,}$/;
function isValidCveId(cveId) {
  return typeof cveId === 'string' && CVE_ID_PATTERN.test(cveId);
}

function isValidVendor(vendor) {
  return typeof vendor === 'string' && vendor.trim().length > 0 && vendor.length <= 200;
}

function createArcherTicketsRouter() {
  const router = express.Router();

  // Get all Archer tickets (with optional filters)
  router.get('/', requireAuth(), async (req, res) => {
    const { cve_id, vendor, status } = req.query;

    let query = 'SELECT * FROM archer_tickets WHERE 1=1';
    const params = [];
    let paramIndex = 1;

    if (cve_id) {
      query += ` AND cve_id = $${paramIndex++}`;
      params.push(cve_id);
    }
    if (vendor) {
      query += ` AND vendor = $${paramIndex++}`;
      params.push(vendor);
    }
    if (status) {
      query += ` AND status = $${paramIndex++}`;
      params.push(status);
    }

    query += ' ORDER BY created_at DESC';

    try {
      const { rows } = await pool.query(query, params);
      res.json(rows);
    } catch (err) {
      console.error('Error fetching Archer tickets:', err);
      res.status(500).json({ error: 'Internal server error.' });
    }
  });

  // Create Archer ticket
  router.post('/', requireAuth(), requireGroup('Admin', 'Standard_User'), async (req, res) => {
    const { exc_number, archer_url, status, cve_id, vendor } = req.body;

    // Validation
    if (!exc_number || typeof exc_number !== 'string' || exc_number.trim().length === 0) {
      return res.status(400).json({ error: 'EXC number is required.' });
    }
    if (!/^EXC-\d+$/.test(exc_number.trim())) {
      return res.status(400).json({ error: 'EXC number must be in format EXC-XXXX (e.g., EXC-5754).' });
    }
    if (!cve_id || !isValidCveId(cve_id)) {
      return res.status(400).json({ error: 'Valid CVE ID is required.' });
    }
    if (!vendor || !isValidVendor(vendor)) {
      return res.status(400).json({ error: 'Valid vendor is required.' });
    }
    if (archer_url && (typeof archer_url !== 'string' || archer_url.length > 500)) {
      return res.status(400).json({ error: 'Archer URL must be under 500 characters.' });
    }
    if (status && !['Draft', 'Open', 'Under Review', 'Accepted'].includes(status)) {
      return res.status(400).json({ error: 'Invalid status. Must be Draft, Open, Under Review, or Accepted.' });
    }

    const validatedStatus = status || 'Draft';

    try {
      const { rows } = await pool.query(
        `INSERT INTO archer_tickets (exc_number, archer_url, status, cve_id, vendor, created_by)
         VALUES ($1, $2, $3, $4, $5, $6)
         RETURNING id`,
        [exc_number.trim(), archer_url || null, validatedStatus, cve_id, vendor, req.user.id]
      );

      logAudit({
        userId: req.user.id,
        action: 'CREATE_ARCHER_TICKET',
        entityType: 'archer_ticket',
        entityId: String(rows[0].id),
        details: { exc_number, archer_url, status: validatedStatus, cve_id, vendor },
        ipAddress: req.ip
      });

      res.status(201).json({
        id: rows[0].id,
        message: 'Archer ticket created successfully'
      });
    } catch (err) {
      console.error('Error creating Archer ticket:', err);
      if (err.code === '23505') {
        return res.status(409).json({ error: 'An Archer ticket with this EXC number already exists.' });
      }
      res.status(500).json({ error: 'Internal server error.' });
    }
  });

  // Update Archer ticket
  router.put('/:id', requireAuth(), requireGroup('Admin', 'Standard_User'), async (req, res) => {
    const { id } = req.params;
    const { exc_number, archer_url, status } = req.body;

    // Validation
    if (exc_number !== undefined) {
      if (typeof exc_number !== 'string' || exc_number.trim().length === 0) {
        return res.status(400).json({ error: 'EXC number cannot be empty.' });
      }
      if (!/^EXC-\d+$/.test(exc_number.trim())) {
        return res.status(400).json({ error: 'EXC number must be in format EXC-XXXX (e.g., EXC-5754).' });
      }
    }
    if (archer_url !== undefined && archer_url !== null && (typeof archer_url !== 'string' || archer_url.length > 500)) {
      return res.status(400).json({ error: 'Archer URL must be under 500 characters.' });
    }
    if (status !== undefined && !['Draft', 'Open', 'Under Review', 'Accepted'].includes(status)) {
      return res.status(400).json({ error: 'Invalid status. Must be Draft, Open, Under Review, or Accepted.' });
    }

    try {
      const { rows } = await pool.query('SELECT * FROM archer_tickets WHERE id = $1', [id]);
      const existing = rows[0];
      if (!existing) {
        return res.status(404).json({ error: 'Archer ticket not found.' });
      }

      const updates = [];
      const params = [];
      let paramIndex = 1;

      if (exc_number !== undefined) {
        updates.push(`exc_number = $${paramIndex++}`);
        params.push(exc_number.trim());
      }
      if (archer_url !== undefined) {
        updates.push(`archer_url = $${paramIndex++}`);
        params.push(archer_url || null);
      }
      if (status !== undefined) {
        updates.push(`status = $${paramIndex++}`);
        params.push(status);
      }

      if (updates.length === 0) {
        return res.status(400).json({ error: 'No fields to update.' });
      }

      updates.push('updated_at = NOW()');
      params.push(id);

      const result = await pool.query(
        `UPDATE archer_tickets SET ${updates.join(', ')} WHERE id = $${paramIndex}`,
        params
      );

      logAudit({
        userId: req.user.id,
        action: 'UPDATE_ARCHER_TICKET',
        entityType: 'archer_ticket',
        entityId: String(id),
        details: { before: existing, changes: req.body },
        ipAddress: req.ip
      });

      res.json({ message: 'Archer ticket updated successfully', changes: result.rowCount });
    } catch (err) {
      console.error(err);
      if (err.code === '23505') {
        return res.status(409).json({ error: 'An Archer ticket with this EXC number already exists.' });
      }
      res.status(500).json({ error: 'Internal server error.' });
    }
  });

  // Delete Archer ticket
  router.delete('/:id', requireAuth(), requireGroup('Admin', 'Standard_User'), async (req, res) => {
    const { id } = req.params;

    try {
      const { rows } = await pool.query('SELECT * FROM archer_tickets WHERE id = $1', [id]);
      const ticket = rows[0];
      if (!ticket) {
        return res.status(404).json({ error: 'Archer ticket not found.' });
      }

      // Admin bypasses all delete restrictions
      if (req.user.group === 'Admin') {
        return performArcherDelete();
      }

      // Standard_User: ownership check
      if (ticket.created_by && ticket.created_by !== req.user.id) {
        return res.status(403).json({ error: 'You can only delete resources you created' });
      }

      // Standard_User: compliance linkage check
      const excNumber = ticket.exc_number;
      try {
        const { rows: compLinks } = await pool.query(
          `SELECT ci.id, ci.extra_json
           FROM compliance_items ci
           JOIN compliance_uploads cu ON ci.upload_id = cu.id
           WHERE ci.status = 'active' AND ci.extra_json ILIKE $1`,
          [`%${excNumber}%`]
        );

        const isLinked = (compLinks || []).some(cl => {
          const json = cl.extra_json || '';
          return json.includes(excNumber);
        });

        if (isLinked) {
          return res.status(403).json({ error: 'Cannot delete ticket linked to compliance report. Contact an admin.' });
        }
      } catch (compErr) {
        if (!compErr.message.includes('does not exist')) throw compErr;
      }

      return performArcherDelete();

      async function performArcherDelete() {
        await pool.query('DELETE FROM archer_tickets WHERE id = $1', [id]);

        logAudit({
          userId: req.user.id,
          action: 'DELETE_ARCHER_TICKET',
          entityType: 'archer_ticket',
          entityId: String(id),
          details: { deleted: ticket },
          ipAddress: req.ip
        });

        res.json({ message: 'Archer ticket deleted successfully' });
      }
    } catch (err) {
      console.error(err);
      res.status(500).json({ error: 'Internal server error.' });
    }
  });

  // GET /status-trend — ticket counts grouped by creation date + status
  router.get('/status-trend', requireAuth(), async (req, res) => {
    try {
      const { rows } = await pool.query(
        `SELECT DATE(created_at) AS date, status, COUNT(*) AS count
         FROM archer_tickets
         GROUP BY DATE(created_at), status
         ORDER BY date ASC`
      );
      res.json({ statusTrend: rows });
    } catch (err) {
      console.error('Error fetching Archer status trend:', err);
      res.status(500).json({ error: 'Internal server error.' });
    }
  });

  return router;
}

module.exports = createArcherTicketsRouter;
