import { existsSync } from "node:fs";
import { join } from "node:path";
import Fastify, { type FastifyInstance } from "fastify";
import cors from "@fastify/cors";
import fastifyStatic from "@fastify/static";
import { env } from "../config/env.js";
import { authPlugin } from "../auth/plugin.js";
import { authRoutes } from "./routes/auth.js";
import { accountRoutes } from "./routes/accounts.js";
import { adRoutes } from "./routes/ads.js";
import { orderRoutes } from "./routes/orders.js";
import { pricingRoutes } from "./routes/pricing.js";
import { templateRoutes } from "./routes/templates.js";
import { counterpartyRoutes } from "./routes/counterparties.js";
import { settingsRoutes } from "./routes/settings.js";
import { syncRoutes } from "./routes/sync.js";

/**
 * Builder da aplicação Fastify (API REST do painel). Separado do bootstrap
 * (`main.ts`) para facilitar testes.
 */
export async function buildServer(): Promise<FastifyInstance> {
  const app = Fastify({
    logger: {
      // Não logar Authorization/cookies para não vazar token de sessão.
      redact: ["req.headers.authorization", "req.headers.cookie"],
    },
  });

  // CORS: em produção o frontend é servido junto; em dev (Vite) liberamos.
  await app.register(cors, {
    origin: env.NODE_ENV === "production" ? false : true,
    credentials: true,
  });

  await app.register(authPlugin);

  // Health-check público.
  app.get("/health", async () => ({ status: "ok" }));

  // Rotas da API sob o prefixo /api (separa do SPA servido no mesmo host).
  await app.register(
    async (api) => {
      await api.register(authRoutes);
      await api.register(accountRoutes);
      await api.register(adRoutes);
      await api.register(orderRoutes);
      await api.register(pricingRoutes);
      await api.register(templateRoutes);
      await api.register(counterpartyRoutes);
      await api.register(settingsRoutes);
      await api.register(syncRoutes);
    },
    { prefix: "/api" },
  );

  // Em produção, serve o frontend buildado (web/dist) no mesmo host, com
  // fallback de SPA: rotas GET que não são /api caem no index.html.
  const distDir = join(process.cwd(), "web", "dist");
  if (existsSync(join(distDir, "index.html"))) {
    await app.register(fastifyStatic, { root: distDir });
    app.setNotFoundHandler((req, reply) => {
      if (req.method === "GET" && !req.url.startsWith("/api")) {
        return reply.sendFile("index.html");
      }
      return reply.code(404).send({ error: "Não encontrado." });
    });
  }

  return app;
}
