import swaggerJsdoc from "swagger-jsdoc";
import { schemas } from "./openapi/schemas";
import { adminPaths, adminTags } from "./openapi/adminPaths";
import { trackerPaths, trackerTags } from "./openapi/trackerPaths";
import { employeePaths, employeeTags } from "./openapi/employeePaths";
import { publicPaths, publicTags } from "./openapi/publicPaths";

type PathItem = Record<string, unknown>;

// The same URL can carry operations from different sections (e.g. admin POST
// and employee GET on /api/games/spin), so merge per HTTP method instead of
// letting a later section overwrite the whole path item.
const mergePaths = (...groups: Record<string, PathItem>[]) =>
  groups.reduce<Record<string, PathItem>>((merged, group) => {
    for (const [path, item] of Object.entries(group)) {
      const existing = merged[path] ?? {};
      for (const method of Object.keys(item)) {
        if (method in existing) throw new Error(`Duplicate OpenAPI operation: ${method.toUpperCase()} ${path}`);
      }
      merged[path] = { ...existing, ...item };
    }
    return merged;
  }, {});

const options: swaggerJsdoc.Options = {
  definition: {
    openapi: "3.0.0",
    info: {
      title: "EGLogics Employee Engagement API",
      version: "1.0.0",
      description: [
        "REST API for the Employee Engagement platform, grouped by client:",
        "",
        "- **Admin** — admin panel (`AdminBearerAuth`)",
        "- **Tracker App** — desktop time tracker (`UserBearerAuth`, employee login)",
        "- **Employee App** — employee web/mobile app (`UserBearerAuth`)",
        "- **Public** — no login (interview quiz links, legal pages)",
        "",
        "**Auth:** send `Authorization: Bearer <accessToken>`. Admin and employee tokens are not interchangeable — " +
          "an employee token on an admin route returns 403 and vice versa. Refresh tokens live in httpOnly cookies " +
          "(`adminRefreshToken` / `userRefreshToken`).",
        "",
        "**Responses:** JSON endpoints return `{ success, status_code, message, data, errors, pagination }`. " +
          "`pagination` is `{ total, page, limit, totalPages, hasNextPage, hasPrevPage }` on paginated endpoints and `null` otherwise. " +
          "On errors `success` is false, `data` is null and `errors` repeats the message.",
        "",
        "**Time zone:** formatted date strings (e.g. `2026-09-30 09:31:05`) are Asia/Kolkata local time; ISO strings are UTC.",
      ].join("\n"),
    },
    servers: [
      { url: "https://tracker-api.eglogics.com", description: "Production" },
      { url: "https://emp-eng-api.stagingwebsite.uk", description: "Staging" },
      { url: "http://localhost:3000", description: "Development" },
    ],
    components: {
      securitySchemes: {
        AdminBearerAuth: {
          type: "http",
          scheme: "bearer",
          bearerFormat: "JWT",
          description: "Admin access token from POST /api/auth/admin/login or /api/auth/verify-otp",
        },
        UserBearerAuth: {
          type: "http",
          scheme: "bearer",
          bearerFormat: "JWT",
          description: "Employee access token from POST /api/auth/user/login (Employee App and Tracker App)",
        },
      },
      schemas,
    },
    // Tag order is the section order in Swagger UI.
    tags: [...adminTags, ...trackerTags, ...employeeTags, ...publicTags],
    paths: mergePaths(adminPaths, trackerPaths, employeePaths, publicPaths),
  },
  apis: [],
};

export const swaggerSpec = swaggerJsdoc(options);
