import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import { withTenant } from '../data/db.js';

const listQuerySchema = z.object({
  page: z.coerce.number().min(1).default(1),
  limit: z.coerce.number().min(1).max(100).default(20),
  status: z.enum(['open', 'acknowledged', 'snoozed', 'expected', 'resolved']).optional(),
  account_id: z.string().optional(),
  min_score: z.coerce.number().min(0).max(100).optional(),
});

export function registerAnomalyRoutes(app: FastifyInstance) {
  // List anomalies
  app.get('/api/v1/anomalies', async (req, reply) => {
    const query = listQuerySchema.parse(req.query);
    const tenantId = (req as any).tenantId;
    const offset = (query.page - 1) * query.limit;

    const result = await withTenant(tenantId, async (client) => {
      let sql = 'SELECT * FROM anomalies WHERE 1=1';
      const params: any[] = [];
      let idx = 1;

      if (query.status) { sql += ` AND status = $${idx++}`; params.push(query.status); }
      if (query.account_id) { sql += ` AND account_id = $${idx++}`; params.push(query.account_id); }
      if (query.min_score) { sql += ` AND score >= $${idx++}`; params.push(query.min_score); }

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

      return client.query(sql, params);
    });

    return { anomalies: result.rows, page: query.page, limit: query.limit };
  });

  // Acknowledge anomaly
  app.post('/api/v1/anomalies/:id/acknowledge', async (req, reply) => {
    const { id } = req.params as { id: string };
    const tenantId = (req as any).tenantId;

    await withTenant(tenantId, async (client) => {
      await client.query("UPDATE anomalies SET status = 'acknowledged' WHERE id = $1 AND status = 'open'", [id]);
    });
    return { status: 'acknowledged' };
  });

  // Snooze anomaly
  app.post('/api/v1/anomalies/:id/snooze', async (req, reply) => {
    const { id } = req.params as { id: string };
    const { hours } = z.object({ hours: z.coerce.number().min(1).max(168).default(24) }).parse(req.body ?? {});
    const tenantId = (req as any).tenantId;

    await withTenant(tenantId, async (client) => {
      await client.query(
        "UPDATE anomalies SET status = 'snoozed', snoozed_until = now() + $1 * interval '1 hour' WHERE id = $2",
        [hours, id],
      );
    });
    return { status: 'snoozed', until_hours: hours };
  });

  // Mark as expected (recurring cost)
  app.post('/api/v1/anomalies/:id/expected', async (req, reply) => {
    const { id } = req.params as { id: string };
    const tenantId = (req as any).tenantId;

    await withTenant(tenantId, async (client) => {
      await client.query("UPDATE anomalies SET status = 'expected' WHERE id = $1", [id]);
    });
    return { status: 'expected' };
  });

  // Dashboard summary
  app.get('/api/v1/dashboard', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    const result = await withTenant(tenantId, async (client) => {
      const openCount = await client.query("SELECT COUNT(*)::int as count FROM anomalies WHERE status = 'open'");
      const topResources = await client.query(`
        SELECT resource_type, COUNT(*)::int as anomaly_count, AVG(score)::numeric(5,2) as avg_score
        FROM anomalies WHERE status = 'open'
        GROUP BY resource_type ORDER BY anomaly_count DESC LIMIT 10
      `);
      const recentTrend = await client.query(`
        SELECT date_trunc('hour', detected_at) as hour, COUNT(*)::int as count
        FROM anomalies WHERE detected_at > now() - interval '24 hours'
        GROUP BY hour ORDER BY hour
      `);
      return {
        open_anomalies: openCount.rows[0]?.count ?? 0,
        top_resources: topResources.rows,
        hourly_trend: recentTrend.rows,
      };
    });

    return result;
  });
}
