import Fastify from "fastify";
import cookie from "@fastify/cookie";
import cors from "@fastify/cors";
import formbody from "@fastify/formbody";
import multipart from "@fastify/multipart";

import { corsOrigins, env } from "./config.js";
import "./types.js";
import { ZodError } from "zod";
import { AppError } from "./lib/errors.js";
import { attachProfile, hydrateAuth } from "./lib/session.js";
import { registerAuthRoutes } from "./routes/auth.js";
import { registerAccountRoutes } from "./routes/account.js";
import { registerOrganizationRoutes } from "./routes/organizations.js";
import { registerBrandKitRoutes } from "./routes/brand-kit.js";
import { registerContactRoutes } from "./routes/contacts.js";
import { registerCampaignRoutes } from "./routes/campaigns.js";
import { registerAnalyticsRoutes } from "./routes/analytics.js";
import { registerAdminRoutes } from "./routes/admin.js";
import { registerPublicRoutes } from "./routes/public.js";
import { registerWebhookRoutes } from "./routes/webhooks.js";

export function buildApp() {
  const app = Fastify({
    logger: true
  });

  app.register(cookie);
  app.register(cors, {
    origin: (origin, callback) => {
      if (!origin || corsOrigins.includes(origin)) {
        callback(null, true);
        return;
      }

      callback(new Error("Origin is not allowed by CORS."), false);
    },
    credentials: true,
    methods: ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
    allowedHeaders: ["Content-Type", "Authorization"],
    preflight: true
  });
  app.register(formbody);
  app.register(multipart, {
    limits: {
      fileSize: 10 * 1024 * 1024,
      files: 1
    }
  });

  app.addHook("onRequest", async (request, reply) => {
    await hydrateAuth(request, reply);
    await attachProfile(request, reply);
  });

  app.get("/api/health", async () => ({
    status: "ok",
    service: "nextacom-api",
    time: new Date().toISOString()
  }));

  registerAuthRoutes(app);
  registerAccountRoutes(app);
  registerOrganizationRoutes(app);
  registerBrandKitRoutes(app);
  registerContactRoutes(app);
  registerCampaignRoutes(app);
  registerAnalyticsRoutes(app);
  registerAdminRoutes(app);
  registerPublicRoutes(app);
  registerWebhookRoutes(app);

  app.setErrorHandler((error, _request, reply) => {
    if (error instanceof AppError) {
      return reply.status(error.statusCode).send({
        error: error.code,
        message: error.message,
        details: error.details ?? null
      });
    }

    if (error instanceof ZodError) {
      return reply.status(400).send({
        error: "VALIDATION_ERROR",
        message: error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "),
        details: error.issues
      });
    }

    app.log.error(error);
    return reply.status(500).send({
      error: "INTERNAL_SERVER_ERROR",
      message: error instanceof Error ? error.message : "An unexpected error occurred."
    });
  });

  return app;
}
