import { spawn } from "node:child_process";
import { createServer } from "node:http";
import { chmodSync, existsSync, lstatSync, mkdirSync, symlinkSync } from "node:fs";
import path from "node:path";

import { serveCloudWeb } from "/app/internal/dev-entrypoint/cloud-web-runtime.mjs";

const serviceId = process.env.HWLAB_SERVICE_ID || "hwlab-unknown";
const environment = process.env.HWLAB_ENVIRONMENT || "dev";
const runtimeKind = process.env.HWLAB_ARTIFACT_KIND || "health-placeholder";
const entrypoint = process.env.HWLAB_SERVICE_ENTRYPOINT || "";
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "8080", 10);

function ensureCodeAgentRuntimeBase() {
  if (serviceId !== "hwlab-cloud-api") return;
  const workspace = process.env.HWLAB_CODE_AGENT_CODEX_WORKSPACE || process.env.HWLAB_CODE_AGENT_WORKSPACE || "/workspace/hwlab";
  const codexHome = process.env.CODEX_HOME || process.env.HWLAB_CODE_AGENT_CODEX_HOME || "/codex-home";
  process.env.HWLAB_CODE_AGENT_WORKSPACE = process.env.HWLAB_CODE_AGENT_WORKSPACE || workspace;
  process.env.HWLAB_CODE_AGENT_CODEX_WORKSPACE = process.env.HWLAB_CODE_AGENT_CODEX_WORKSPACE || workspace;
  process.env.HWLAB_CODE_AGENT_CODEX_SANDBOX = process.env.HWLAB_CODE_AGENT_CODEX_SANDBOX || "danger-full-access";
  process.env.HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED = process.env.HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED || "1";
  process.env.HWLAB_CODE_AGENT_CODEX_STDIO_SUPERVISOR = process.env.HWLAB_CODE_AGENT_CODEX_STDIO_SUPERVISOR || "repo-owned";
  process.env.HWLAB_CODE_AGENT_PROVIDER = process.env.HWLAB_CODE_AGENT_PROVIDER || "codex-stdio";
  process.env.CODEX_HOME = codexHome;
  process.env.HWLAB_CODE_AGENT_CODEX_COMMAND = process.env.HWLAB_CODE_AGENT_CODEX_COMMAND || "/app/node_modules/.bin/codex";
  process.env.HWLAB_CODE_AGENT_SKILLS_DIRS = process.env.HWLAB_CODE_AGENT_SKILLS_DIRS || "/app/skills";

  mkdirSync(path.dirname(workspace), { recursive: true });
  if (!existsSync(workspace)) {
    if (workspace === "/workspace/hwlab" && existsSync("/app")) {
      symlinkSync("/app", workspace, "dir");
    } else {
      mkdirSync(workspace, { recursive: true });
    }
  }
  mkdirSync(codexHome, { recursive: true });
  for (const target of [workspace, codexHome]) {
    try {
      const info = lstatSync(target);
      chmodSync(info.isSymbolicLink() ? path.resolve(target) : target, 0o777);
    } catch {
      // Runtime readiness reports the concrete blocker without exposing secret values.
    }
  }
}

ensureCodeAgentRuntimeBase();

function sendJson(response, statusCode, body) {
  const payload = JSON.stringify(body, null, 2);
  response.writeHead(statusCode, {
    "content-type": "application/json; charset=utf-8",
    "content-length": Buffer.byteLength(payload)
  });
  response.end(payload);
}

function healthPayload() {
  const commitId = process.env.HWLAB_COMMIT_ID || process.env.HWLAB_GIT_SHA || "unknown";
  const imageReference = process.env.HWLAB_IMAGE || "unknown";
  const imageTag = imageTagFromReference(imageReference) || shortRevision(commitId);
  const buildCreatedAt = normalizeIsoTimestamp(
    process.env.HWLAB_BUILD_CREATED_AT ||
    process.env.HWLAB_IMAGE_CREATED_AT ||
    process.env.SOURCE_DATE_EPOCH ||
    process.env.BUILD_DATE
  );
  const buildSource = process.env.HWLAB_BUILD_SOURCE || "runtime-env";
  return {
    serviceId,
    environment,
    status: "ok",
    artifactKind: runtimeKind,
    revision: process.env.HWLAB_REVISION || commitId,
    commit: {
      id: commitId,
      source: buildSource
    },
    image: {
      reference: imageReference,
      tag: imageTag,
      digest: process.env.HWLAB_IMAGE_DIGEST || "unknown"
    },
    build: {
      createdAt: buildCreatedAt,
      source: buildSource,
      provenance: process.env.HWLAB_BUILD_PROVENANCE || null,
      metadataSource: buildCreatedAt ? "runtime-env:HWLAB_BUILD_CREATED_AT" : "unavailable",
      unavailableReason: buildCreatedAt ? null : "HWLAB_BUILD_CREATED_AT missing from runtime environment"
    }
  };
}

function normalizeIsoTimestamp(value) {
  const source = String(value || "").trim();
  if (!source) return null;
  if (/^\d+$/u.test(source)) {
    const seconds = Number.parseInt(source, 10);
    if (Number.isSafeInteger(seconds)) {
      const date = new Date(seconds * 1000);
      if (Number.isFinite(date.getTime())) return date.toISOString();
    }
  }
  const date = new Date(source);
  return Number.isFinite(date.getTime()) ? date.toISOString() : null;
}

function imageTagFromReference(imageReference) {
  const source = String(imageReference || "").trim();
  const slashIndex = source.lastIndexOf("/");
  const colonIndex = source.lastIndexOf(":");
  if (colonIndex <= slashIndex) return null;
  return source.slice(colonIndex + 1) || null;
}

function shortRevision(value) {
  const source = String(value || "").trim();
  return source.length >= 7 ? source.slice(0, 7) : source || "unknown";
}

function runEntrypoint(command, args) {
  const child = spawn(command, args, {
    cwd: "/app",
    env: process.env,
    stdio: "inherit"
  });
  child.on("error", (error) => {
    process.stderr.write(JSON.stringify({
      serviceId,
      status: "failed",
      error: "entrypoint_spawn_failed",
      command,
      reason: error.message
    }) + "\n");
    process.exit(127);
  });
  child.on("exit", (code, signal) => {
    if (signal) process.kill(process.pid, signal);
    else process.exit(code ?? 0);
  });
}

function runNodeEntrypoint(file) {
  runEntrypoint(process.execPath, [file]);
}

function runBunEntrypoint(file) {
  const candidates = [
    process.env.HWLAB_BUN_COMMAND,
    "/app/node_modules/.bin/bun",
    "/usr/local/bin/bun",
    "bun"
  ].filter(Boolean);
  const command = candidates.find((candidate) => !candidate.includes("/") || existsSync(candidate)) || "bun";
  runEntrypoint(command, [file]);
}

function serveHealthOnly() {
  const server = createServer((request, response) => {
    const url = new URL(request.url || "/", "http://hwlab-artifact.local");
    if (url.pathname === "/health/live" || url.pathname === "/health") {
      sendJson(response, 200, healthPayload());
      return;
    }
    sendJson(response, 404, { error: "not_found", serviceId, path: url.pathname });
  });
  server.listen(port, "0.0.0.0", () => {
    process.stdout.write(JSON.stringify({ serviceId, environment, status: "listening", port }) + "\n");
  });
}

if (runtimeKind === "node-command" && entrypoint) {
  runNodeEntrypoint(entrypoint);
} else if (runtimeKind === "bun-command" && entrypoint) {
  runBunEntrypoint(entrypoint);
} else if (runtimeKind === "cloud-web") {
  await serveCloudWeb({ port, serviceId, healthPayload, sendJson });
} else {
  serveHealthOnly();
}
