import type { FastifyInstance } from 'fastify';
import { authenticate, requireRole } from '../middleware/auth.js';
import { integrationSettingsService } from '../services/integrations/integrationSettingsService.js';
import { ticketSyncService } from '../services/integrations/ticketSyncService.js';
import {
  INTEGRATION_PROVIDERS,
  type IntegrationProvider,
} from '../services/integrations/types.js';
import { userCanAccessTicket } from '../services/ticketAccessService.js';

const adminGuard = [authenticate, requireRole('admin')];
const staffGuard = [authenticate, requireRole('admin', 'user')];

function parseProvider(raw: string): IntegrationProvider | null {
  return (INTEGRATION_PROVIDERS as readonly string[]).includes(raw)
    ? (raw as IntegrationProvider)
    : null;
}

export async function integrationRoutes(fastify: FastifyInstance) {
  // Admin: list integration settings (secrets masked)
  fastify.get('/', { preHandler: adminGuard }, async (_req, reply) => {
    return reply.send(await integrationSettingsService.list());
  });

  // Staff: which providers are ready to sync
  fastify.get('/enabled', { preHandler: staffGuard }, async (_req, reply) => {
    return reply.send(await integrationSettingsService.getEnabled());
  });

  fastify.put('/:provider', { preHandler: adminGuard }, async (req, reply) => {
    const provider = parseProvider((req.params as { provider: string }).provider);
    if (!provider) return reply.status(400).send({ error: 'Unknown provider' });
    const body = req.body as {
      enabled?: boolean;
      config?: Record<string, string>;
      api_key?: string | null;
      token?: string | null;
      password?: string | null;
    };
    const saved = await integrationSettingsService.upsert(provider, body);
    return reply.send(saved);
  });

  fastify.get('/tickets/:ticketId/links', { preHandler: staffGuard }, async (req, reply) => {
    const { ticketId } = req.params as { ticketId: string };
    if (!(await userCanAccessTicket(req.user!, ticketId))) {
      return reply.status(403).send({ error: 'Forbidden' });
    }
    return reply.send(await ticketSyncService.listLinks(ticketId));
  });

  fastify.get('/tickets/:ticketId/preview/:provider', { preHandler: staffGuard }, async (req, reply) => {
    const { ticketId, provider: raw } = req.params as { ticketId: string; provider: string };
    const provider = parseProvider(raw);
    if (!provider) return reply.status(400).send({ error: 'Unknown provider' });
    if (!(await userCanAccessTicket(req.user!, ticketId))) {
      return reply.status(403).send({ error: 'Forbidden' });
    }
    try {
      return reply.send(await ticketSyncService.preview(ticketId, provider));
    } catch (e: unknown) {
      const err = e as { statusCode?: number; message?: string };
      return reply.status(err.statusCode ?? 500).send({ error: err.message ?? 'Preview failed' });
    }
  });

  fastify.post('/tickets/:ticketId/sync/:provider', { preHandler: staffGuard }, async (req, reply) => {
    const { ticketId, provider: raw } = req.params as { ticketId: string; provider: string };
    const provider = parseProvider(raw);
    if (!provider) return reply.status(400).send({ error: 'Unknown provider' });
    if (!(await userCanAccessTicket(req.user!, ticketId))) {
      return reply.status(403).send({ error: 'Forbidden' });
    }
    const body = (req.body ?? {}) as { fields?: Record<string, string> };
    try {
      const result = await ticketSyncService.sync(
        ticketId,
        provider,
        req.user!.sub,
        body.fields ?? {},
      );
      return reply.status(201).send(result);
    } catch (e: unknown) {
      const err = e as { statusCode?: number; message?: string; external_url?: string };
      return reply.status(err.statusCode ?? 500).send({
        error: err.message ?? 'Sync failed',
        external_url: err.external_url,
      });
    }
  });
}
