export const defaultNativeKubeconfig = "/etc/rancher/k3s/k3s.yaml";
export const requiredNativeNodeName = "d601";

export type K3sGuardStatus = "pass" | "refused" | "blocked";

export interface K3sTargetObservation {
  kubeconfig: string;
  expectedKubeconfig?: string;
  currentContext: string | null;
  apiServer: string | null;
  nodeNames: string[];
  commandsOk: boolean;
  combinedText: string;
}

export interface K3sDefaultKubectlDiagnostic {
  checked: boolean;
  currentContext: string | null;
  apiServer: string | null;
  refusalSignals: string[];
  status: "clean" | "stale-forbidden-default" | "unavailable";
  summary: string;
}

export interface K3sGuardClassification {
  status: K3sGuardStatus;
  refusal: boolean;
  refusalSignals: string[];
  kubeconfig: string;
  expectedKubeconfig: string;
  currentContext: string | null;
  apiServer: string | null;
  nodeNames: string[];
  nodeCount: number;
  requiredNodeName: string;
  requiredNodePresent: boolean;
  commandsOk: boolean;
  defaultKubectlDiagnostic?: K3sDefaultKubectlDiagnostic;
  summary: string;
}

export interface K3sGuardShellOptions {
  passOutput?: "stdout" | "stderr" | "quiet";
}

function uniqueSignals(signals: Array<string | null>): string[] {
  return [...new Set(signals.filter((signal): signal is string => signal !== null))];
}

export function forbiddenKubeSignals(text: string): string[] {
  return uniqueSignals([
    /docker-desktop/iu.test(text) ? "docker-desktop" : null,
    /desktop-control-plane/iu.test(text) ? "desktop-control-plane" : null,
    /127\.0\.0\.1:11700/u.test(text) ? "127.0.0.1:11700" : null,
  ]);
}

export function classifyDefaultKubectlDiagnostic(input: {
  currentContext: string | null;
  apiServer: string | null;
  combinedText: string;
  commandsOk: boolean;
}): K3sDefaultKubectlDiagnostic {
  const refusalSignals = forbiddenKubeSignals(input.combinedText);
  if (!input.commandsOk) {
    return {
      checked: true,
      currentContext: input.currentContext,
      apiServer: input.apiServer,
      refusalSignals,
      status: "unavailable",
      summary: "Default kubectl diagnostic could not read context/server; this does not block the explicit target.",
    };
  }
  if (refusalSignals.length > 0) {
    return {
      checked: true,
      currentContext: input.currentContext,
      apiServer: input.apiServer,
      refusalSignals,
      status: "stale-forbidden-default",
      summary: "Default kubectl resolves to a forbidden local control-plane signal; explicit KUBECONFIG remains the deploy target.",
    };
  }
  return {
    checked: true,
    currentContext: input.currentContext,
    apiServer: input.apiServer,
    refusalSignals,
    status: "clean",
    summary: "Default kubectl diagnostic did not show Docker Desktop control-plane signals.",
  };
}

export function classifyK3sTarget(
  observation: K3sTargetObservation,
  defaultKubectlDiagnostic?: K3sDefaultKubectlDiagnostic,
): K3sGuardClassification {
  const expectedKubeconfig = observation.expectedKubeconfig ?? defaultNativeKubeconfig;
  const refusalSignals = forbiddenKubeSignals(observation.combinedText);
  const requiredNodePresent = observation.nodeNames.includes(requiredNativeNodeName);
  const wrongKubeconfig = observation.kubeconfig !== expectedKubeconfig;
  const refusal = refusalSignals.length > 0;
  const status: K3sGuardStatus = refusal
    ? "refused"
    : !observation.commandsOk || wrongKubeconfig || !requiredNodePresent
      ? "blocked"
      : "pass";
  const defaultStale = defaultKubectlDiagnostic?.status === "stale-forbidden-default";
  const summary = refusal
    ? "Refusing k3s operation because the explicit target kubeconfig resolved to a forbidden Docker Desktop control-plane signal."
    : wrongKubeconfig
      ? `k3s target guard blocked: expected explicit KUBECONFIG=${expectedKubeconfig}.`
      : !observation.commandsOk
        ? "k3s target guard blocked: explicit target kubeconfig could not read context, server, and nodes."
        : !requiredNodePresent
          ? `k3s target guard blocked: explicit target kubeconfig did not report node ${requiredNativeNodeName}.`
          : defaultStale
            ? "native k3s target guard passed with explicit KUBECONFIG; stale default kubectl context was observed only as a diagnostic."
            : "native k3s target guard passed with explicit KUBECONFIG.";
  return {
    status,
    refusal,
    refusalSignals,
    kubeconfig: observation.kubeconfig,
    expectedKubeconfig,
    currentContext: observation.currentContext,
    apiServer: observation.apiServer,
    nodeNames: observation.nodeNames,
    nodeCount: observation.nodeNames.length,
    requiredNodeName: requiredNativeNodeName,
    requiredNodePresent,
    commandsOk: observation.commandsOk,
    ...(defaultKubectlDiagnostic === undefined ? {} : { defaultKubectlDiagnostic }),
    summary,
  };
}

function shellQuote(value: string): string {
  return `'${value.replace(/'/gu, "'\\''")}'`;
}

export function k3sGuardShellLines(kubeconfig = defaultNativeKubeconfig, options: K3sGuardShellOptions = {}): string[] {
  const passOutput = options.passOutput ?? "stdout";
  const passLine = passOutput === "quiet"
    ? ":"
    : passOutput === "stderr"
      ? "printf 'k3s_target_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\" >&2"
      : "printf 'k3s_target_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\"";
  return [
    `export KUBECONFIG=${shellQuote(kubeconfig)}`,
    "k3s_target_guard() {",
    `  required_kubeconfig=${shellQuote(kubeconfig)}`,
    `  required_node=${shellQuote(requiredNativeNodeName)}`,
    "  if [ \"${KUBECONFIG:-}\" != \"$required_kubeconfig\" ]; then",
    "    printf 'k3s_target_guard=blocked reason=wrong-kubeconfig expected=%s actual=%s\\n' \"$required_kubeconfig\" \"${KUBECONFIG:-<unset>}\" >&2",
    "    return 1",
    "  fi",
    "  if ! command -v kubectl >/dev/null 2>&1; then",
    "    echo 'k3s_target_guard=blocked reason=kubectl-missing' >&2",
    "    return 1",
    "  fi",
    "  if ! context=$(kubectl config current-context 2>&1); then",
    "    printf 'k3s_target_guard=blocked reason=context-read-failed detail=%s\\n' \"$context\" >&2",
    "    return 1",
    "  fi",
    "  if ! server=$(kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}' 2>&1); then",
    "    printf 'k3s_target_guard=blocked reason=server-read-failed detail=%s\\n' \"$server\" >&2",
    "    return 1",
    "  fi",
    "  if ! nodes=$(kubectl get nodes -o 'jsonpath={range .items[*]}{.metadata.name}{\"\\n\"}{end}' 2>&1); then",
    "    printf 'k3s_target_guard=blocked reason=nodes-read-failed detail=%s\\n' \"$nodes\" >&2",
    "    return 1",
    "  fi",
    "  combined=$(printf '%s\\n%s\\n%s\\n' \"$context\" \"$server\" \"$nodes\")",
    "  if printf '%s\\n' \"$combined\" | grep -Eiq 'docker-desktop|desktop-control-plane|127\\.0\\.0\\.1:11700'; then",
    "    printf 'k3s_target_guard=refused reason=forbidden-control-plane context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2",
    "    return 1",
    "  fi",
    "  if ! printf '%s\\n' \"$nodes\" | grep -Fx \"$required_node\" >/dev/null; then",
    "    printf 'k3s_target_guard=blocked reason=missing-required-node context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2",
    "    return 1",
    "  fi",
    `  ${passLine}`,
    "}",
    "k3s_target_guard",
  ];
}
