import type { FastifyInstance } from 'fastify';
import pino from 'pino';
import { Redis } from 'ioredis';
import { withTenant, pool } from '../data/db.js';
import { config } from '../config/index.js';
import { AwsDiscoveryScanner } from '../discovery/aws-scanner.js';
import { GitHubDiscoveryScanner } from '../discovery/github-scanner.js';
import { CatalogService } from '../catalog/service.js';
import { ScheduledDiscovery } from '../discovery/scheduler.js';

const logger = pino({ name: 'api-discovery' });
const redis = new Redis(config.REDIS_URL);
const scheduler = new ScheduledDiscovery(redis, pool);
const catalog = new CatalogService(pool);

export function registerDiscoveryRoutes(app: FastifyInstance) {
  // Trigger AWS discovery scan
  app.post('/api/v1/discovery/aws', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    // Get tenant's AWS config
    const tenantConfig = await withTenant(tenantId, async (client) => {
      return client.query('SELECT * FROM tenants WHERE id = $1', [tenantId]);
    });

    const result = await scheduler.runScan(tenantId, 'aws');
    logger.info({ tenantId, result: result.status }, 'AWS discovery scan completed');
    return reply.status(202).send({ status: result.status, discovered: result.discovered });
  });

  // Trigger GitHub discovery scan
  app.post('/api/v1/discovery/github', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    const result = await scheduler.runScan(tenantId, 'github');
    logger.info({ tenantId, result: result.status }, 'GitHub discovery scan completed');
    return reply.status(202).send({ status: result.status, discovered: result.discovered });
  });

  // Get scan history
  app.get('/api/v1/discovery/history', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    const result = await withTenant(tenantId, async (client) => {
      return client.query('SELECT * FROM scan_history ORDER BY started_at DESC LIMIT 20');
    });

    return { scans: result.rows };
  });

  // List staged updates (from partial scans)
  app.get('/api/v1/discovery/staged', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    const result = await withTenant(tenantId, async (client) => {
      return client.query("SELECT * FROM staged_updates WHERE status = 'pending' ORDER BY created_at DESC");
    });

    return { staged: result.rows };
  });

  // Apply or reject staged update
  app.post('/api/v1/discovery/staged/:id/:action', async (req, reply) => {
    const { id, action } = req.params as { id: string; action: string };
    const tenantId = (req as any).tenantId;

    if (action !== 'apply' && action !== 'reject') {
      return reply.status(400).send({ error: 'Action must be apply or reject' });
    }

    const newStatus = action === 'apply' ? 'applied' : 'rejected';

    await withTenant(tenantId, async (client) => {
      await client.query('UPDATE staged_updates SET status = $1 WHERE id = $2', [newStatus, id]);
      // If applied, merge staged changes into services table
      if (action === 'apply') {
        const staged = await client.query('SELECT * FROM staged_updates WHERE id = $1', [id]);
        if (staged.rows[0]) {
          const changes = staged.rows[0].changes;
          await client.query(
            `INSERT INTO services (tenant_id, name, type, owner, owner_source, tags, last_discovered_at)
             VALUES ($1, $2, $3, $4, $5, $6, now())
             ON CONFLICT (tenant_id, name) DO UPDATE SET
               type = COALESCE(EXCLUDED.type, services.type),
               owner = COALESCE(EXCLUDED.owner, services.owner),
               tags = services.tags || EXCLUDED.tags,
               last_discovered_at = now(), updated_at = now()`,
            [tenantId, staged.rows[0].service_name, changes.type, changes.owner, changes.ownerSource ?? 'heuristic', JSON.stringify(changes.tags ?? {})],
          );
        }
      }
    });

    return { status: newStatus };
  });
}
