import z from "zod/v4";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { auth } from "./utils/auth";
import { Log } from "@nestri/core/utils/log";
import { HTTPException } from "hono/http-exception";
import { VisibleError, ErrorCodes } from "@nestri/core/error";
import { openAPIRouteHandler, validator } from "hono-openapi";
import packageJson from "../../package.json" assert { type: "json" };

const log = Log.create({ service: "api" });

export const app = new Hono();
app
  .use(async (c, next) => {
    c.header("Cache-Control", "no-store");
    return next();
  })
  .use(async (c, next) => {
    log.info("request", {
      method: c.req.method,
      path: c.req.path,
    });
    const start = Date.now();
    await next();
    log.info("response", {
      duration: Date.now() - start,
    });
  })
  .use(
    validator("header", z.object({ "x-nestri-steam": z.string().optional() })),
  )
  .use(validator("query", z.object({ steamID: z.string().optional() })))
  .use(auth)
  .use(cors());

export const routes = app
  .get("/", async (c) => {
    return c.text("ok");
  })
  .onError((error, c) => {
    // Handle our custom VisibleError
    if (error instanceof VisibleError) {
      return c.json(error.toResponse(), error.statusCode());
    }

    // Handle HTTP exceptions
    if (error instanceof HTTPException) {
      console.error("http error:", error);
      return c.json(
        {
          type: "validation",
          code: ErrorCodes.Validation.INVALID_PARAMETER,
          message: "Invalid request",
        },
        400,
      );
    }

    // Handle any other errors as internal server errors
    log.error("Unhandled API error:", { error });
    return c.json(
      {
        type: "internal",
        code: ErrorCodes.Server.INTERNAL_ERROR,
        message: "Internal server error",
      },
      500,
    );
  });

app.get(
  "/doc",
  openAPIRouteHandler(routes, {
    documentation: {
      info: {
        title: "Nestri API",
        termsOfService: "https://nestri.io/terms",
        description:
          "The Nestri API gives you the power deploy and stream games/apps in the cloud. Run on our GPUs or bring your own.",
        version: packageJson.version ?? "1.0.0",
      },
      components: {
        securitySchemes: {
          Bearer: {
            type: "http",
            scheme: "bearer",
            bearerFormat: "JWT",
          },
          SteamID: {
            type: "apiKey",
            description: "The steamID to use for this query",
            in: "header",
            name: "x-nestri-steam",
          },
        },
      },
      security: [{ Bearer: [], SteamID: [] }],
      servers: [
        { description: "Production", url: "https://api.nestri.io" },
        { description: "Sandbox", url: "https://api.dev.nestri.io" },
      ],
    },
  }),
);

export default {
  port: 3001,
  fetch: app.fetch,
};
