import { CLOUD_API_SERVICE_ID } from "../audit/index.mjs";
import { getHeader, parsePositiveInteger, readBody, sendJson } from "./server-http-utils.ts";
import {
  getSkillTree,
  listSkills,
  readSkillTextFile,
  uploadUserSkill
} from "./skills-store.ts";

const DEFAULT_SKILL_UPLOAD_BODY_LIMIT_BYTES = 16 * 1024 * 1024;

export async function handleSkillsHttp(request, response, url, options = {}) {
  try {
    if (request.method === "GET" && url.pathname === "/v1/skills") {
      sendJson(response, 200, await listSkills({ env: options.env ?? process.env }));
      return;
    }

    if (request.method === "POST" && url.pathname === "/v1/skills/uploads") {
      const payload = await readJsonBody(request, skillUploadBodyLimit(options.env));
      sendJson(response, 201, await uploadUserSkill(payload, { env: options.env ?? process.env }));
      return;
    }

    const treeMatch = url.pathname.match(/^\/v1\/skills\/([^/]+)\/tree$/u);
    if (request.method === "GET" && treeMatch) {
      sendJson(response, 200, await getSkillTree(decodeURIComponent(treeMatch[1]), { env: options.env ?? process.env }));
      return;
    }

    const fileMatch = url.pathname.match(/^\/v1\/skills\/([^/]+)\/files$/u);
    if (request.method === "GET" && fileMatch) {
      sendJson(
        response,
        200,
        await readSkillTextFile(decodeURIComponent(fileMatch[1]), url.searchParams.get("path") || "SKILL.md", { env: options.env ?? process.env })
      );
      return;
    }

    sendJson(response, 404, skillsErrorPayload(404, "skill_route_not_found", "Skill route is not implemented.", request));
  } catch (error) {
    const statusCode = Number.isInteger(error?.statusCode) ? error.statusCode : 500;
    sendJson(response, statusCode, skillsErrorPayload(statusCode, error?.code || "skill_request_failed", error?.message || "Skill request failed.", request));
  }
}

async function readJsonBody(request, limitBytes) {
  const body = await readBody(request, limitBytes);
  try {
    return body ? JSON.parse(body) : {};
  } catch (error) {
    const wrapped = new Error(`Invalid JSON body: ${error.message}`);
    Object.assign(wrapped, { statusCode: 400, code: "parse_error" });
    throw wrapped;
  }
}

function skillUploadBodyLimit(env = process.env) {
  return parsePositiveInteger(env?.HWLAB_SKILL_UPLOAD_BODY_LIMIT_BYTES, DEFAULT_SKILL_UPLOAD_BODY_LIMIT_BYTES);
}

function skillsErrorPayload(statusCode, code, message, request) {
  return {
    serviceId: CLOUD_API_SERVICE_ID,
    route: request?.url || "/v1/skills",
    status: "failed",
    error: {
      code,
      message,
      httpStatus: statusCode,
      traceId: getHeader(request, "x-trace-id") || null
    }
  };
}
