import path from 'path';
import fs from 'fs';
import type { FastifyInstance } from 'fastify';
import fastifyStatic from '@fastify/static';
import rateLimit from '@fastify/rate-limit';
import { config } from '../config';
import { extractClientIp } from '../geo';
import { ensureAnalyticsAdminUser } from './services/auth';
import { analyticsAuthRoutes } from './routes/auth';
import { analyticsCollectRoutes } from './routes/collect';
import { analyticsMetricsRoutes } from './routes/metrics';
import { startAnalyticsJobs } from './jobs';

function resolvePath(...segments: string[]): string {
  return path.join(process.cwd(), ...segments);
}

export async function registerAnalyticsRoutes(app: FastifyInstance): Promise<void> {
  if (!config.analytics.enabled) return;

  await ensureAnalyticsAdminUser();
  startAnalyticsJobs();

  const publicDir = resolvePath('public');
  const analyticsJs = path.join(publicDir, 'analytics.js');
  if (fs.existsSync(analyticsJs)) {
    app.get('/analytics.js', async (_request, reply) => {
      reply.header('Cache-Control', 'public, max-age=3600');
      return reply.type('application/javascript').send(fs.readFileSync(analyticsJs));
    });
  }

  const dashboardDir = resolvePath('analytics-dashboard', 'dist');
  const dashboardIndex = path.join(dashboardDir, 'index.html');
  if (fs.existsSync(dashboardIndex)) {
    app.get(config.analytics.dashboardPath, async (_request, reply) => {
      return reply.redirect(`${config.analytics.dashboardPath}/`);
    });

    await app.register(
      async (dashboardApp) => {
        await dashboardApp.register(fastifyStatic, {
          root: dashboardDir,
          prefix: '/',
          decorateReply: false,
        });

        dashboardApp.setNotFoundHandler(async (_request, reply) => {
          reply.header(
            'Content-Security-Policy',
            "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'",
          );
          return reply.type('text/html; charset=UTF-8').send(fs.readFileSync(dashboardIndex));
        });
      },
      { prefix: config.analytics.dashboardPath },
    );
  }

  await app.register(
    async (authApi) => {
      await authApi.register(rateLimit, { global: false });
      await authApi.register(analyticsAuthRoutes);
    },
    { prefix: config.analytics.apiPrefix },
  );

  await app.register(
    async (collectApi) => {
      await collectApi.register(rateLimit, {
        max: config.analytics.collectRateLimit,
        timeWindow: '1 minute',
        keyGenerator: (request) => `analytics-collect:${extractClientIp(request)}`,
      });
      await collectApi.register(analyticsCollectRoutes);
    },
    { prefix: config.analytics.apiPrefix },
  );

  await app.register(analyticsMetricsRoutes, { prefix: config.analytics.apiPrefix });
}
