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

const logger = pino({ name: 'api-notifications' });

const notifConfigSchema = z.object({
  channel: z.enum(['slack', 'email', 'webhook']),
  config: z.object({
    slack_webhook_url: z.string().url().optional(),
    email_to: z.string().email().optional(),
    webhook_url: z.string().url().optional(),
  }),
  min_severity: z.enum(['critical', 'high', 'medium', 'low', 'info']).default('medium'),
  enabled: z.boolean().default(true),
});

export function registerNotificationRoutes(app: FastifyInstance) {
  // List notification configs
  app.get('/api/v1/notifications', async (req, reply) => {
    const tenantId = (req as any).tenantId;
    const result = await withTenant(tenantId, async (client) => {
      return client.query('SELECT * FROM notification_configs ORDER BY channel');
    });
    return { configs: result.rows };
  });

  // Upsert notification config
  app.put('/api/v1/notifications/:channel', async (req, reply) => {
    const { channel } = req.params as { channel: string };
    const body = notifConfigSchema.parse({ ...req.body as any, channel });
    const tenantId = (req as any).tenantId;

    await withTenant(tenantId, async (client) => {
      await client.query(
        `INSERT INTO notification_configs (tenant_id, channel, config, min_severity, enabled)
         VALUES ($1, $2, $3, $4, $5)
         ON CONFLICT (tenant_id, channel) DO UPDATE SET config = $3, min_severity = $4, enabled = $5`,
        [tenantId, body.channel, JSON.stringify(body.config), body.min_severity, body.enabled],
      );
    });

    logger.info({ tenantId, channel }, 'Notification config updated');
    return { status: 'updated', channel };
  });

  // Test notification
  app.post('/api/v1/notifications/:channel/test', async (req, reply) => {
    const { channel } = req.params as { channel: string };
    const tenantId = (req as any).tenantId;

    const configResult = await withTenant(tenantId, async (client) => {
      return client.query('SELECT * FROM notification_configs WHERE channel = $1', [channel]);
    });

    const cfg = configResult.rows[0];
    if (!cfg) return reply.status(404).send({ error: `No ${channel} config found` });

    const { SlackNotifier, EmailNotifier, WebhookNotifier } = await import('../notifications/dispatcher.js');
    const testIncident = {
      incidentId: 'test-000',
      title: '[TEST] dd0c/alert notification test',
      severity: 'info',
      service: 'test-service',
      alertCount: 1,
      firstAlertAt: new Date(),
      fingerprint: 'test',
      dashboardUrl: `https://alert.dd0c.dev/incidents/test-000`,
    };

    let sent = false;
    if (channel === 'slack' && cfg.config?.slack_webhook_url) {
      sent = await new SlackNotifier(cfg.config.slack_webhook_url).send(testIncident);
    } else if (channel === 'email' && cfg.config?.email_to) {
      sent = await new EmailNotifier(process.env.RESEND_API_KEY ?? '', 'alerts@dd0c.dev', cfg.config.email_to).send(testIncident);
    } else if (channel === 'webhook' && cfg.config?.webhook_url) {
      sent = await new WebhookNotifier(cfg.config.webhook_url).send(testIncident);
    }

    logger.info({ tenantId, channel, sent }, 'Test notification sent');
    return { status: sent ? 'sent' : 'failed', channel };
  });
}
