import { Router, Request, Response } from 'express';
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
import { authMiddleware } from '../middleware/auth';
import { auditAdminAccess, requireAdminAccess } from '../middleware/admin';
import { getLogoStats, getUnresolvedTeams, getLogoRecord, upsertLogoRecord, getLogoCoverage, getRecentLogos, getNeedsReviewLogos } from '../models/logo';
import { resolveTeamLogo, getLogoPath, normalizeAbbr, getLogoLeague } from '../services/team-asset';

const router = Router();
const adminMiddleware = [authMiddleware, requireAdminAccess, auditAdminAccess('logos')] as const;

// GET /api/logos/stats — coverage stats by league (public)
router.get('/stats', async (_req: Request, res: Response) => {
  try {
    const stats = await getLogoStats();
    const total = stats.reduce((sum, s) => sum + Number(s.total), 0);
    const resolved = stats.reduce((sum, s) => sum + Number(s.resolved), 0);
    res.json({
      total,
      resolved,
      coverage: total > 0 ? Math.round((resolved / total) * 1000) / 10 : 0,
      byLeague: stats,
    });
  } catch (err) {
    console.error('Logo stats error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// GET /api/logos/missing — teams with failed resolution (admin only)
router.get('/missing', ...adminMiddleware, async (_req: Request, res: Response) => {
  try {
    const unresolved = await getUnresolvedTeams();
    res.json({ count: unresolved.length, teams: unresolved });
  } catch (err) {
    console.error('Logo missing error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// ── Admin endpoints (weatherman-only) for CRM integration ──
// These must stay above /:league/:abbr so Express does not treat "admin"
// as a dynamic league param.

// GET /api/logos/admin/coverage — per-league breakdown
router.get('/admin/coverage', ...adminMiddleware, async (_req: Request, res: Response) => {
  try {
    const coverage = await getLogoCoverage();
    const totals = coverage.reduce(
      (acc, c) => ({
        total: acc.total + c.total,
        resolved: acc.resolved + c.resolved,
        fallback: acc.fallback + c.fallback,
        failed: acc.failed + c.failed,
      }),
      { total: 0, resolved: 0, fallback: 0, failed: 0 }
    );
    res.json({ totals, byLeague: coverage });
  } catch (err) {
    console.error('Logo admin coverage error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// GET /api/logos/admin/recent — last 20 logos updated
router.get('/admin/recent', ...adminMiddleware, async (_req: Request, res: Response) => {
  try {
    const recent = await getRecentLogos(20);
    res.json({ logos: recent });
  } catch (err) {
    console.error('Logo admin recent error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// GET /api/logos/admin/needs-review — teams on fallback or failed
router.get('/admin/needs-review', ...adminMiddleware, async (_req: Request, res: Response) => {
  try {
    const teams = await getNeedsReviewLogos();
    res.json({ count: teams.length, teams });
  } catch (err) {
    console.error('Logo admin needs-review error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// POST /api/logos/admin/retry/:league/:abbr — re-trigger full pipeline for one team
router.post('/admin/retry/:league/:abbr', ...adminMiddleware, async (req: Request, res: Response) => {
  try {
    const league = req.params.league as string;
    const abbr = req.params.abbr as string;
    const logoLeague = getLogoLeague(league);
    const normalizedAbbr = normalizeAbbr(abbr);

    // Get team name from existing record
    const existing = await getLogoRecord(logoLeague, normalizedAbbr);
    const teamName = existing?.team_name || abbr;

    // Delete existing PNG to force full re-resolution
    const logoPath = getLogoPath(league, abbr);
    try { fs.unlinkSync(logoPath); } catch {}

    const result = await resolveTeamLogo(league, abbr, teamName, true);
    res.json(result);
  } catch (err) {
    console.error('Logo admin retry error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// GET /api/logos/:league/:abbr — provenance for a specific logo (public)
router.get('/:league/:abbr', async (req: Request, res: Response) => {
  try {
    const league = req.params.league as string;
    const abbr = req.params.abbr as string;
    const logoLeague = getLogoLeague(league);
    const normalizedAbbr = normalizeAbbr(abbr);
    const record = await getLogoRecord(logoLeague, normalizedAbbr);
    if (!record) {
      res.status(404).json({ error: 'Logo record not found' });
      return;
    }
    res.json(record);
  } catch (err) {
    console.error('Logo lookup error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// POST /api/logos/:league/:abbr/override — manual PNG upload (admin)
router.post('/:league/:abbr/override', ...adminMiddleware, async (req: Request, res: Response) => {
  try {
    const league = req.params.league as string;
    const abbr = req.params.abbr as string;
    const logoLeague = getLogoLeague(league);
    const normalizedAbbr = normalizeAbbr(abbr);
    const destPath = getLogoPath(league, abbr);

    // Expect raw PNG body
    const chunks: Buffer[] = [];
    for await (const chunk of req) {
      chunks.push(Buffer.from(chunk));
    }
    const buf = Buffer.concat(chunks);

    // Validate PNG
    const PNG_MAGIC = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
    if (buf.length < 8 || !buf.subarray(0, 8).equals(PNG_MAGIC)) {
      res.status(400).json({ error: 'File must be a valid PNG' });
      return;
    }
    if (buf.length > 2 * 1024 * 1024) {
      res.status(400).json({ error: 'File too large (max 2MB)' });
      return;
    }

    // Write file
    const dir = path.dirname(destPath);
    if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(destPath + '.tmp', buf);
    fs.renameSync(destPath + '.tmp', destPath);

    const checksum = crypto.createHash('sha256').update(buf).digest('hex');

    await upsertLogoRecord(logoLeague, normalizedAbbr, {
      file_path: `/logos/${logoLeague}/${normalizedAbbr}.png`,
      file_exists: true,
      checksum_sha256: checksum,
      source: 'manual',
      resolution_status: 'resolved',
      admin_override: true,
    });

    res.json({ success: true, league: logoLeague, abbr: normalizedAbbr, checksum });
  } catch (err) {
    console.error('Logo override error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// POST /api/logos/sync — trigger on-demand sync (admin)
router.post('/sync', ...adminMiddleware, async (req: Request, res: Response) => {
  try {
    const { league: targetLeague, abbr: targetAbbr, teamName } = req.body || {};

    if (targetLeague && targetAbbr) {
      // Resolve a single team
      const result = await resolveTeamLogo(targetLeague, targetAbbr, teamName, true);
      res.json(result);
    } else {
      res.status(400).json({ error: 'Provide league and abbr to sync a specific team' });
    }
  } catch (err) {
    console.error('Logo sync error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

export default router;
