import { Router, Response } from 'express';
import { authMiddleware, requireAdmin, AuthRequest } from '../middleware/auth';
import { getAllUsers, findUserById, updateUserRole, freezeUser } from '../models/user';
import { query } from '../db';
import { listPm2Processes } from '../lib/pm2';

const router = Router();

// All admin routes require auth + admin role
router.use(authMiddleware);
router.use(requireAdmin);

// --- User Management ---

// List all users
router.get('/users', async (req: AuthRequest, res: Response) => {
  try {
    const users = await getAllUsers();
    res.json({ users });
  } catch (error) {
    console.error('Admin list users error:', error);
    res.status(500).json({ error: 'Failed to list users' });
  }
});

// Promote/demote user role
router.put('/users/:id/role', async (req: AuthRequest, res: Response) => {
  try {
    const { id } = req.params;
    const { role } = req.body;

    if (!role || !['user', 'admin'].includes(role)) {
      return res.status(400).json({ error: 'Invalid role. Must be "user" or "admin"' });
    }

    const target = await findUserById(id);
    if (!target) {
      return res.status(404).json({ error: 'User not found' });
    }

    await updateUserRole(id, role);

    // Log to admin audit
    await query(
      `INSERT INTO sc_admin_log (admin_id, action, target_id, details) VALUES ($1, $2, $3, $4)`,
      [req.userId, `role_change_to_${role}`, id, JSON.stringify({ from: target.role, to: role })]
    );

    res.json({ success: true, message: `User role updated to ${role}` });
  } catch (error) {
    console.error('Admin role change error:', error);
    res.status(500).json({ error: 'Failed to update role' });
  }
});

// Freeze/unfreeze user account
router.put('/users/:id/freeze', async (req: AuthRequest, res: Response) => {
  try {
    const { id } = req.params;
    const { frozen } = req.body;

    const target = await findUserById(id);
    if (!target) {
      return res.status(404).json({ error: 'User not found' });
    }

    await freezeUser(id, !!frozen);

    await query(
      `INSERT INTO sc_admin_log (admin_id, action, target_id, details) VALUES ($1, $2, $3, $4)`,
      [req.userId, frozen ? 'account_freeze' : 'account_unfreeze', id, JSON.stringify({ frozen: !!frozen })]
    );

    res.json({ success: true, message: `Account ${frozen ? 'frozen' : 'unfrozen'}` });
  } catch (error) {
    console.error('Admin freeze error:', error);
    res.status(500).json({ error: 'Failed to update account' });
  }
});

// --- Audit Log ---

router.get('/audit', async (req: AuthRequest, res: Response) => {
  try {
    const limit = Math.min(parseInt(req.query.limit as string) || 50, 200);
    const offset = parseInt(req.query.offset as string) || 0;

    const result = await query(
      `SELECT al.*,
              au.email as admin_email,
              tu.email as target_email
       FROM sc_admin_log al
       LEFT JOIN sc_users au ON al.admin_id = au.id
       LEFT JOIN sc_users tu ON al.target_id = tu.id
       ORDER BY al.created_at DESC
       LIMIT $1 OFFSET $2`,
      [limit, offset]
    );

    res.json({ entries: result.rows });
  } catch (error) {
    console.error('Admin audit error:', error);
    res.status(500).json({ error: 'Failed to get audit log' });
  }
});

// --- System Health ---

// Global state overview
router.get('/system/health', async (req: AuthRequest, res: Response) => {
  try {
    const stateResult = await query(`SELECT * FROM sc_global_state WHERE id = 'primary'`);
    const state = stateResult.rows[0];

    // Count unresolved events by severity
    const eventsResult = await query(
      `SELECT severity, COUNT(*) as count
       FROM sc_system_events
       WHERE resolved = FALSE
       GROUP BY severity`
    );

    const unresolvedEvents: Record<string, number> = {};
    for (const row of eventsResult.rows) {
      unresolvedEvents[row.severity] = parseInt(row.count);
    }

    res.json({
      global_state: state,
      unresolved_events: unresolvedEvents,
    });
  } catch (error) {
    console.error('Admin health error:', error);
    res.status(500).json({ error: 'Failed to get health' });
  }
});

// PM2 processes status
router.get('/system/processes', async (req: AuthRequest, res: Response) => {
  try {
    const summary = await listPm2Processes();
    res.json({ processes: summary });
  } catch (error) {
    console.error('Admin processes error:', error);
    res.status(500).json({ error: 'Failed to get processes' });
  }
});

// System events
router.get('/system/events', async (req: AuthRequest, res: Response) => {
  try {
    const limit = Math.min(parseInt(req.query.limit as string) || 50, 200);
    const offset = parseInt(req.query.offset as string) || 0;
    const severity = req.query.severity as string;
    const source = req.query.source as string;
    const unresolved = req.query.unresolved === 'true';

    let sql = `SELECT * FROM sc_system_events WHERE 1=1`;
    const params: any[] = [];
    let paramIdx = 1;

    if (severity) {
      sql += ` AND severity = $${paramIdx++}`;
      params.push(severity);
    }
    if (source) {
      sql += ` AND source = $${paramIdx++}`;
      params.push(source);
    }
    if (unresolved) {
      sql += ` AND resolved = FALSE`;
    }

    sql += ` ORDER BY created_at DESC LIMIT $${paramIdx++} OFFSET $${paramIdx++}`;
    params.push(limit, offset);

    const result = await query(sql, params);
    res.json({ events: result.rows });
  } catch (error) {
    console.error('Admin events error:', error);
    res.status(500).json({ error: 'Failed to get events' });
  }
});

// Data freshness check
router.get('/system/data-freshness', async (req: AuthRequest, res: Response) => {
  try {
    // Check key data tables for freshness
    const checks = await Promise.all([
      query(`SELECT MAX("updatedAt") as latest FROM "PlayerPropLine"`).catch(() => ({ rows: [{ latest: null }] })),
      query(`SELECT MAX("updatedAt") as latest FROM "PlayerInjury"`).catch(() => ({ rows: [{ latest: null }] })),
      query(`SELECT MAX("updatedAt") as latest FROM "SportsGame"`).catch(() => ({ rows: [{ latest: null }] })),
      query(`SELECT MAX(published_at) as latest FROM sc_blog_posts WHERE status = 'published'`).catch(() => ({ rows: [{ latest: null }] })),
    ]);

    const now = new Date();
    const freshness = [
      { source: 'PlayerPropLine', latest: checks[0].rows[0]?.latest, maxAge: '2h' },
      { source: 'PlayerInjury', latest: checks[1].rows[0]?.latest, maxAge: '6h' },
      { source: 'SportsGame', latest: checks[2].rows[0]?.latest, maxAge: '2h' },
      { source: 'BlogPosts', latest: checks[3].rows[0]?.latest, maxAge: '24h' },
    ].map(f => {
      const ageMs = f.latest ? now.getTime() - new Date(f.latest).getTime() : Infinity;
      const maxAgeMs = parseInt(f.maxAge) * (f.maxAge.includes('h') ? 3600000 : 86400000);
      return {
        ...f,
        age_minutes: f.latest ? Math.round(ageMs / 60000) : null,
        status: ageMs <= maxAgeMs ? 'fresh' : ageMs <= maxAgeMs * 2 ? 'stale' : 'critical',
      };
    });

    res.json({ freshness });
  } catch (error) {
    console.error('Admin data freshness error:', error);
    res.status(500).json({ error: 'Failed to check freshness' });
  }
});

// Manual unfreeze system
router.post('/system/unfreeze', async (req: AuthRequest, res: Response) => {
  try {
    await query(
      `UPDATE sc_global_state
       SET mode = 'normal', active_freeze_reasons = '[]', last_updated = NOW(), updated_by = $1
       WHERE id = 'primary'`,
      [req.user.email]
    );

    // Log the event
    await query(
      `INSERT INTO sc_system_events (event_type, severity, source, message, details)
       VALUES ('system_unfreeze', 'info', 'admin', $1, $2)`,
      [
        `System manually unfrozen by ${req.user.email}`,
        JSON.stringify({ admin_id: req.userId }),
      ]
    );

    await query(
      `INSERT INTO sc_admin_log (admin_id, action, details) VALUES ($1, $2, $3)`,
      [req.userId, 'system_unfreeze', JSON.stringify({ previous_mode: 'frozen' })]
    );

    res.json({ success: true, message: 'System unfrozen' });
  } catch (error) {
    console.error('Admin unfreeze error:', error);
    res.status(500).json({ error: 'Failed to unfreeze' });
  }
});

export default router;
