import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyBaseLogger } from 'fastify';
import type { Sql } from '../db.js';
import { generateReport, runReportSchedulerTick } from '../services/reports.js';
import { jsonbObject } from '../services/jsonb.js';

/**
 * P6.2: Reports tab API + scheduled digest.
 *
 * GET  /api/reports            — list generated reports (newest first)
 * GET  /api/reports/:id        — single report (markdown + stats)
 * POST /api/reports/generate   — manually trigger a digest now
 * GET  /api/reports/schedule   — current schedule meta
 * POST /api/reports/schedule   — update schedule meta {interval, enabled}
 */
export function registerReportRoutes(app: FastifyInstance, sql: Sql): void {
  app.get('/api/reports', async (_req: FastifyRequest, reply: FastifyReply) => {
    const rows = await sql<{
      id: string;
      kind: string;
      interval: string;
      period_start: string;
      period_end: string;
      created_at: string;
    }[]>`
      SELECT id, kind, interval, period_start, period_end, created_at
      FROM control_reports
      ORDER BY created_at DESC
      LIMIT 100
    `;
    return reply.send({
      reports: rows.map((r) => ({
        id: r.id,
        kind: r.kind,
        interval: r.interval,
        periodStart: r.period_start,
        periodEnd: r.period_end,
        createdAt: r.created_at,
      })),
    });
  });

  app.get('/api/reports/:id', async (req: FastifyRequest, reply: FastifyReply) => {
    const { id } = req.params as { id: string };
    const rows = await sql<{
      id: string;
      kind: string;
      interval: string;
      period_start: string;
      period_end: string;
      markdown: string;
      stats: unknown;
      created_at: string;
    }[]>`
      SELECT id, kind, interval, period_start, period_end, markdown, stats, created_at
      FROM control_reports WHERE id = ${id}
    `;
    if (rows.length === 0) {
      return reply.status(404).send({ error: 'report not found' });
    }
    const r = rows[0]!;
    return reply.send({
      id: r.id,
      kind: r.kind,
      interval: r.interval,
      periodStart: r.period_start,
      periodEnd: r.period_end,
      markdown: r.markdown,
      stats: jsonbObject(r.stats),
      createdAt: r.created_at,
    });
  });

  app.post('/api/reports/generate', async (req: FastifyRequest, reply: FastifyReply) => {
    const body = (req.body as Record<string, unknown>) ?? {};
    const interval = body.interval === 'weekly' ? 'weekly' : 'daily';
    const id = await generateReport(sql, interval);
    return reply.status(201).send({ id });
  });

  app.get('/api/reports/schedule', async (_req: FastifyRequest, reply: FastifyReply) => {
    const rows = await sql<{ interval: string; enabled: boolean; last_run_at: string | null }[]>`
      SELECT interval, enabled, last_run_at FROM control_schedule_meta WHERE name = 'report-digest'
    `;
    const m = rows[0];
    return reply.send({
      interval: m?.interval ?? 'daily',
      enabled: m?.enabled ?? true,
      lastRunAt: m?.last_run_at ?? null,
    });
  });

  app.post('/api/reports/schedule', async (req: FastifyRequest, reply: FastifyReply) => {
    const body = (req.body as Record<string, unknown>) ?? {};
    const interval = body.interval === 'weekly' ? 'weekly' : 'daily';
    const enabled = body.enabled !== false;
    await sql`
      UPDATE control_schedule_meta
      SET interval = ${interval}, enabled = ${enabled}
      WHERE name = 'report-digest'
    `;
    return reply.send({ interval, enabled });
  });
}

/**
 * Start the in-process report scheduler: an immediate catch-up tick on boot,
 * then hourly. Returns a stop function for onClose.
 */
export function startReportScheduler(sql: Sql, log: FastifyBaseLogger): () => void {
  const tick = async () => {
    try {
      const result = await runReportSchedulerTick(sql);
      if (result.ran) log.info({ reportId: result.reportId }, 'reports: digest generated');
    } catch (err) {
      log.warn({ err: (err as Error).message }, 'reports: scheduler tick failed');
    }
  };
  // Catch-up on boot.
  void tick();
  const timer = setInterval(tick, 3600_000); // hourly
  return () => clearInterval(timer);
}
