import { join } from "node:path";
import { SEAT_GUARD_REL } from "./seat-constants.mjs";

export const SEAT_SANDBOX_SETTINGS = Object.freeze({
  enabled: true,
  allowUnsandboxedCommands: false,
  failIfUnavailable: true,
  autoAllowBashIfSandboxed: true,
  excludedCommands: [],
  network: Object.freeze({
    strictAllowlist: true,
    allowedDomains: [],
    allowLocalBinding: true,
    allowUnixSockets: [],
  }),
});

export function buildSeatSettings(model) {
  return {
    enableWorkflows: false,
    availableModels: [model],
    permissions: { deny: ["Agent", "Workflow"] },
    enabledPlugins: {},
    extraKnownMarketplaces: {},
    sandbox: { ...SEAT_SANDBOX_SETTINGS, network: { ...SEAT_SANDBOX_SETTINGS.network } },
  };
}

function sandboxSettingsMatch(settings) {
  const sandbox = settings?.sandbox;
  if (!sandbox) return false;
  return JSON.stringify(sandbox) === JSON.stringify({
    ...SEAT_SANDBOX_SETTINGS,
    network: { ...SEAT_SANDBOX_SETTINGS.network },
  });
}

export function planSeatLaunch({
  boundModel,
  claudeBinary,
  claudeArgv = [],
  settingsDir,
  mcpConfigPath,
  seatEnv = {},
  home = "/home/user",
}) {
  const errors = [];
  if (!claudeBinary || !String(claudeBinary).startsWith("/")) errors.push("claude-binary-not-absolute");
  if (!boundModel) errors.push("missing-bound-model");
  const settingsPath = join(settingsDir, "seat-settings.json");
  const guardBin = join(home, SEAT_GUARD_REL);
  const seatPath = `${guardBin}:${seatEnv.PATH || process.env.PATH || "/usr/bin:/bin"}`;
  const env = {
    ...seatEnv,
    PATH: seatPath,
    OVERDECK_SEAT_MODEL: boundModel,
  };
  const argv = [
    claudeBinary,
    "--model",
    boundModel,
    "--settings",
    settingsPath,
    "--setting-sources",
    "",
    "--disallowedTools",
    "Agent",
    "Workflow",
    "--agents",
    "{}",
    "--strict-mcp-config",
    "--mcp-config",
    mcpConfigPath,
    ...claudeArgv,
  ];
  const modelFlags = argv.filter((a) => a === "--model" || String(a).startsWith("--model="));
  if (modelFlags.length !== 1) errors.push("model-flag-count");
  if (argv.some((a) => a === "--fallback-model" || String(a).startsWith("--fallback-model="))) errors.push("fallback-model-in-argv");
  const settings = buildSeatSettings(boundModel);
  if (settings.availableModels.length !== 1 || settings.availableModels[0] !== boundModel) errors.push("availableModels");
  if (settings.enableWorkflows !== false) errors.push("enableWorkflows");
  if (!settings.permissions?.deny?.includes("Agent") || !settings.permissions?.deny?.includes("Workflow")) errors.push("permissions-deny");
  if (!sandboxSettingsMatch(settings)) errors.push("sandbox-settings");
  return {
    ok: errors.length === 0,
    errors,
    settings,
    settingsPath,
    mcpConfigPath,
    env,
    argv,
    guardBin,
  };
}

export function dryRunSeatLaunchPlan(plan, projectSettings = {}, boundModel = plan?.env?.OVERDECK_SEAT_MODEL) {
  const errors = [...(plan.errors || [])];
  if (projectSettings.enableWorkflows === true) errors.push("project-enableWorkflows");
  const models = projectSettings.availableModels;
  if (Array.isArray(models) && models.length > 1) errors.push("project-availableModels");
  const allow = projectSettings.permissions?.allow;
  if (Array.isArray(allow) && allow.some((v) => v === "Agent" || v === "Workflow")) errors.push("project-permissions-allow");
  if (!plan.argv?.includes("--setting-sources") || plan.argv[plan.argv.indexOf("--setting-sources") + 1] !== "") {
    errors.push("setting-sources-empty");
  }
  if (!plan.argv?.includes("--agents") || plan.argv[plan.argv.indexOf("--agents") + 1] !== "{}") errors.push("agents-empty");
  if (!plan.argv?.includes("--strict-mcp-config")) errors.push("strict-mcp-config");
  if (!plan.argv?.includes("--mcp-config")) errors.push("mcp-config");
  if (!boundModel || !plan.argv?.includes("--model") || plan.argv[plan.argv.indexOf("--model") + 1] !== boundModel) {
    errors.push("model-flag-missing");
  }
  if (!plan.env?.PATH?.startsWith(plan.guardBin)) errors.push("guard-path-prepend");
  if (!sandboxSettingsMatch(plan.settings)) errors.push("sandbox-settings");
  const baseUrl = plan.env?.ANTHROPIC_BASE_URL || "";
  if (baseUrl.includes("127.0.0.1") || baseUrl.includes("localhost")) errors.push("proxy-loopback-url");
  return { ok: errors.length === 0, errors };
}
