import { ALL_REGISTRY_ADDONS, DEFAULT_ADDONS, DEFAULT_PRESETS } from "./core/registry";
import { fetchManifest, applyManifestToEntry, healthCheckAddon } from "./core/manifest";
import type {
  AddonRegistryEntry,
  AddonRegistryResponse,
  AddonStatusResponse,
  AddonHealthCheckResult,
} from "./core/models";

export interface Env {
  // No secrets needed — this is a public registry
}

// ── Route handler ──

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    const corsHeaders = {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type",
    };

    if (request.method === "OPTIONS") {
      return new Response(null, { status: 204, headers: corsHeaders });
    }

    try {
      let response: Response;

      // GET /v1/addons/registry
      if (url.pathname === "/v1/addons/registry" || url.pathname === "/addons/registry") {
        response = await handleRegistry();
      }
      // GET /v1/addons/status
      else if (url.pathname === "/v1/addons/status" || url.pathname === "/addons/status") {
        response = await handleStatus();
      }
      // GET /v1/addons/presets
      else if (url.pathname === "/v1/addons/presets" || url.pathname === "/addons/presets") {
        response = handlePresets();
      }
      // GET /v1/addons/{id}/manifest
      else if (url.pathname.match(/\/v1\/addons\/([^/]+)\/manifest/) || url.pathname.match(/\/addons\/([^/]+)\/manifest/)) {
        const id = url.pathname.split("/")[3];
        response = await handleManifest(id);
      }
      // POST /v1/addons/{id}/health-check
      else if (url.pathname.match(/\/v1\/addons\/([^/]+)\/health-check/) || url.pathname.match(/\/addons\/([^/]+)\/health-check/)) {
        const id = url.pathname.split("/")[3];
        response = await handleHealthCheck(id);
      }
      // GET /v1/health
      else if (url.pathname === "/v1/health" || url.pathname === "/health") {
        response = Response.json({ status: "ok", addonCount: DEFAULT_ADDONS.length });
      }
      else {
        response = Response.json(
          { error: "Not found", endpoints: [
            "GET /v1/addons/registry",
            "GET /v1/addons/status",
            "GET /v1/addons/presets",
            "GET /v1/addons/{id}/manifest",
            "POST /v1/addons/{id}/health-check",
            "GET /v1/health",
          ]},
          { status: 404 },
        );
      }

      // Add CORS headers
      const headers = new Headers(response.headers);
      for (const [key, value] of Object.entries(corsHeaders)) {
        headers.set(key, value);
      }
      return new Response(response.body, {
        status: response.status,
        headers,
      });
    } catch (e) {
      return Response.json(
        { error: "Internal server error", message: (e as Error).message },
        { status: 500, headers: corsHeaders },
      );
    }
  },
};

// ── Handler implementations ──

async function handleRegistry(): Promise<Response> {
  const addons = ALL_REGISTRY_ADDONS.filter((a) => !a.deprecated);
  const presets = DEFAULT_PRESETS;

  const response: AddonRegistryResponse = {
    addons,
    presets,
    updatedAt: new Date().toISOString(),
  };

  return Response.json(response);
}

async function handleStatus(): Promise<Response> {
  const addons = DEFAULT_ADDONS.map((a) => ({
    id: a.id,
    name: a.name,
    health: a.health,
    lastChecked: a.lastChecked,
    manifestResponseMs: null as number | null,
  }));

  const response: AddonStatusResponse = { addons };
  return Response.json(response);
}

function handlePresets(): Response {
  return Response.json({ presets: DEFAULT_PRESETS });
}

async function handleManifest(id: string): Promise<Response> {
  const entry = DEFAULT_ADDONS.find((a) => a.id === id || a.manifestUrl.includes(id));
  if (!entry) {
    return Response.json({ error: "Addon not found" }, { status: 404 });
  }

  // Try live manifest, fall back to cached/registry data
  const liveManifest = await fetchManifest(entry.manifestUrl);
  if (liveManifest) {
    applyManifestToEntry(entry, liveManifest);
    return Response.json(liveManifest);
  }

  // Return synthetic manifest from registry
  return Response.json({
    id: entry.id,
    name: entry.name,
    version: entry.version,
    description: entry.description,
    resources: entry.resources.map((r) => ({ name: r, types: entry.types })),
    types: entry.types,
    idPrefixes: entry.idPrefixes,
    catalogs: entry.catalogs,
    logo: entry.logo,
    background: entry.background,
    behaviorHints: { configurable: entry.configurable },
  });
}

async function handleHealthCheck(id: string): Promise<Response> {
  const entry = DEFAULT_ADDONS.find((a) => a.id === id);
  if (!entry) {
    return Response.json({ error: "Addon not found" }, { status: 404 });
  }

  const result: AddonHealthCheckResult = await healthCheckAddon(entry);

  // Update the registry entry's health
  entry.health = result.status;
  entry.lastChecked = result.checkedAt;

  return Response.json(result);
}
