import { spawnSync } from "node:child_process";
import { createHash } from "node:crypto";
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { dirname, isAbsolute, relative, resolve } from "node:path";
import { type UniDeskConfig, repoRoot, rootPath } from "./config";
import { runSshCommandCapture } from "./ssh";

export interface GithubSshIdentityDistribution {
  ok: boolean;
  detail: string;
  fingerprint: string | null;
  seededFromLocal: boolean;
  identityId?: string;
  targetId?: string;
  configTruth?: Record<string, unknown>;
  raw?: unknown;
}

interface GithubSshIdentity {
  privateKey: string;
  publicKey: string;
  knownHosts: string;
  updatedAt: string | null;
}

interface DeploySshSourceRef {
  sourceRef: string;
  sourceKey: "file";
}

interface DeploySshCreateFromLocal {
  enabled: boolean;
  privateKeyPath: string;
  publicKeyPath: string;
  knownHostsPath: string;
}

interface DeploySshIdentitySpec {
  id: string;
  host: string;
  privateKey: DeploySshSourceRef;
  publicKey: DeploySshSourceRef;
  knownHosts: DeploySshSourceRef;
  createFromLocal: DeploySshCreateFromLocal | null;
}

interface DeploySshTargetSpec {
  targetId: string;
  providerId: string;
  route: string;
  homeDir: string;
  egress: DeploySshEgressSpec;
  identities: string[];
}

type DeploySshEgressSpec =
  | { mode: "direct" }
  | { mode: "http-connect-proxy"; proxyUrl: string };

interface DeploySshIdentityConfig {
  configPath: string;
  sourceRoot: string;
  defaults: {
    targetId: string;
    identityId: string;
  };
  identities: Record<string, DeploySshIdentitySpec>;
  targets: Record<string, DeploySshTargetSpec>;
}

interface ResolvedDeploySshIdentitySourcePaths {
  privateKeyPath: string;
  publicKeyPath: string;
  knownHostsPath: string;
}

interface SourceGithubIdentityResult {
  identity: GithubSshIdentity;
  seededFromLocal: boolean;
}

const deploySshIdentitiesConfigPath = "config/deploy-ssh-identities.yaml";

function asRecord(value: unknown, path: string): Record<string, unknown> {
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${path} must be an object`);
  return value as Record<string, unknown>;
}

function optionalRecord(value: unknown, path: string): Record<string, unknown> | null {
  if (value === undefined || value === null) return null;
  return asRecord(value, path);
}

function stringField(record: Record<string, unknown>, key: string, path: string): string {
  const value = record[key];
  if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${path}.${key} must be a non-empty string`);
  return value.trim();
}

function absolutePathField(record: Record<string, unknown>, key: string, path: string): string {
  const value = stringField(record, key, path);
  if (!isAbsolute(value)) throw new Error(`${path}.${key} must be an absolute path`);
  return value;
}

function booleanField(record: Record<string, unknown>, key: string, path: string): boolean {
  const value = record[key];
  if (typeof value !== "boolean") throw new Error(`${path}.${key} must be a boolean`);
  return value;
}

function stringArrayField(record: Record<string, unknown>, key: string, path: string): string[] {
  const value = record[key];
  if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.trim().length === 0)) {
    throw new Error(`${path}.${key} must be a non-empty string array`);
  }
  return value.map((item) => item.trim());
}

function sourceRefField(record: Record<string, unknown>, key: string, path: string): DeploySshSourceRef {
  const value = asRecord(record[key], `${path}.${key}`);
  const sourceRef = stringField(value, "sourceRef", `${path}.${key}`);
  const sourceKey = stringField(value, "sourceKey", `${path}.${key}`);
  if (sourceKey !== "file") throw new Error(`${path}.${key}.sourceKey must be file`);
  if (isAbsolute(sourceRef) || sourceRef.split(/[\\/]+/u).includes("..")) {
    throw new Error(`${path}.${key}.sourceRef must be a relative path under sources.root`);
  }
  return { sourceRef, sourceKey };
}

function parseDeploySshCreateFromLocal(value: unknown, path: string): DeploySshCreateFromLocal | null {
  const record = optionalRecord(value, path);
  if (record === null) return null;
  return {
    enabled: booleanField(record, "enabled", path),
    privateKeyPath: absolutePathField(record, "privateKeyPath", path),
    publicKeyPath: absolutePathField(record, "publicKeyPath", path),
    knownHostsPath: absolutePathField(record, "knownHostsPath", path),
  };
}

function parseDeploySshIdentity(id: string, value: unknown): DeploySshIdentitySpec {
  const path = `${deploySshIdentitiesConfigPath}#identities.${id}`;
  const record = asRecord(value, path);
  return {
    id,
    host: stringField(record, "host", path),
    privateKey: sourceRefField(record, "privateKey", path),
    publicKey: sourceRefField(record, "publicKey", path),
    knownHosts: sourceRefField(record, "knownHosts", path),
    createFromLocal: parseDeploySshCreateFromLocal(record.createFromLocal, `${path}.createFromLocal`),
  };
}

function parseDeploySshTarget(targetId: string, value: unknown): DeploySshTargetSpec {
  const path = `${deploySshIdentitiesConfigPath}#targets.${targetId}`;
  const record = asRecord(value, path);
  const egress = parseDeploySshEgress(record.egress, `${path}.egress`);
  return {
    targetId,
    providerId: stringField(record, "providerId", path),
    route: stringField(record, "route", path),
    homeDir: absolutePathField(record, "homeDir", path),
    egress,
    identities: stringArrayField(record, "identities", path),
  };
}

function parseDeploySshEgress(value: unknown, path: string): DeploySshEgressSpec {
  const record = asRecord(value, path);
  const mode = stringField(record, "mode", path);
  if (mode === "direct") return { mode };
  if (mode === "http-connect-proxy") return { mode, proxyUrl: stringField(record, "proxyUrl", path) };
  throw new Error(`${path}.mode must be direct or http-connect-proxy`);
}

function loadDeploySshIdentityConfig(): DeploySshIdentityConfig {
  const parsed = Bun.YAML.parse(readFileSync(rootPath(deploySshIdentitiesConfigPath), "utf8")) as unknown;
  const root = asRecord(parsed, deploySshIdentitiesConfigPath);
  if (root.version !== 1) throw new Error(`${deploySshIdentitiesConfigPath}.version must be 1`);
  if (root.kind !== "UnideskDeploySshIdentities") throw new Error(`${deploySshIdentitiesConfigPath}.kind must be UnideskDeploySshIdentities`);
  const defaults = asRecord(root.defaults, `${deploySshIdentitiesConfigPath}.defaults`);
  const sources = asRecord(root.sources, `${deploySshIdentitiesConfigPath}.sources`);
  const identities = asRecord(root.identities, `${deploySshIdentitiesConfigPath}.identities`);
  const targets = asRecord(root.targets, `${deploySshIdentitiesConfigPath}.targets`);
  const config: DeploySshIdentityConfig = {
    configPath: deploySshIdentitiesConfigPath,
    sourceRoot: absolutePathField(sources, "root", `${deploySshIdentitiesConfigPath}.sources`),
    defaults: {
      targetId: stringField(defaults, "targetId", `${deploySshIdentitiesConfigPath}.defaults`),
      identityId: stringField(defaults, "identityId", `${deploySshIdentitiesConfigPath}.defaults`),
    },
    identities: Object.fromEntries(Object.entries(identities).map(([id, value]) => [id, parseDeploySshIdentity(id, value)])),
    targets: Object.fromEntries(Object.entries(targets).map(([id, value]) => [id, parseDeploySshTarget(id, value)])),
  };
  if (config.targets[config.defaults.targetId] === undefined) throw new Error(`${deploySshIdentitiesConfigPath}.defaults.targetId references missing target ${config.defaults.targetId}`);
  if (config.identities[config.defaults.identityId] === undefined) throw new Error(`${deploySshIdentitiesConfigPath}.defaults.identityId references missing identity ${config.defaults.identityId}`);
  for (const target of Object.values(config.targets)) {
    for (const identityId of target.identities) {
      if (config.identities[identityId] === undefined) throw new Error(`${deploySshIdentitiesConfigPath}#targets.${target.targetId}.identities references missing identity ${identityId}`);
    }
  }
  return config;
}

function selectDeploySshTarget(config: DeploySshIdentityConfig, selection: string | null | undefined): { target: DeploySshTargetSpec; defaulted: boolean } {
  const raw = selection === undefined || selection === null || selection.length === 0 ? config.defaults.targetId : selection;
  const target = Object.values(config.targets).find((candidate) => candidate.targetId.toLowerCase() === raw.toLowerCase() || candidate.providerId.toLowerCase() === raw.toLowerCase());
  if (target === undefined) throw new Error(`${config.configPath} has no target ${raw}; known targets: ${Object.keys(config.targets).join(", ")}`);
  return { target, defaulted: raw === config.defaults.targetId && (selection === undefined || selection === null || selection.length === 0) };
}

function selectDeploySshIdentity(config: DeploySshIdentityConfig, target: DeploySshTargetSpec, selection: string | null | undefined): { identity: DeploySshIdentitySpec; defaulted: boolean } {
  const raw = selection === undefined || selection === null || selection.length === 0 ? config.defaults.identityId : selection;
  const identity = config.identities[raw];
  if (identity === undefined) throw new Error(`${config.configPath} has no identity ${raw}; known identities: ${Object.keys(config.identities).join(", ")}`);
  if (!target.identities.includes(identity.id)) throw new Error(`${config.configPath}#targets.${target.targetId}.identities does not include ${identity.id}`);
  return { identity, defaulted: raw === config.defaults.identityId && (selection === undefined || selection === null || selection.length === 0) };
}

function sourceFilePath(config: DeploySshIdentityConfig, sourceRef: string): string {
  const sourceRoot = resolve(config.sourceRoot);
  const resolved = resolve(sourceRoot, sourceRef);
  const rel = relative(sourceRoot, resolved);
  if (rel.startsWith("..") || isAbsolute(rel)) throw new Error(`${deploySshIdentitiesConfigPath} sourceRef escapes sources.root: ${sourceRef}`);
  return resolved;
}

function sourcePaths(config: DeploySshIdentityConfig, identity: DeploySshIdentitySpec): ResolvedDeploySshIdentitySourcePaths {
  return {
    privateKeyPath: sourceFilePath(config, identity.privateKey.sourceRef),
    publicKeyPath: sourceFilePath(config, identity.publicKey.sourceRef),
    knownHostsPath: sourceFilePath(config, identity.knownHosts.sourceRef),
  };
}

function configTruth(config: DeploySshIdentityConfig, target: DeploySshTargetSpec, identity: DeploySshIdentitySpec, targetDefaulted: boolean, identityDefaulted: boolean): Record<string, unknown> {
  return {
    configPath: config.configPath,
    sourceRoot: config.sourceRoot,
    targetPath: `${config.configPath}#targets.${target.targetId}`,
    identityPath: `${config.configPath}#identities.${identity.id}`,
    defaults: {
      targetPath: `${config.configPath}#defaults.targetId`,
      identityPath: `${config.configPath}#defaults.identityId`,
      targetDefaulted,
      identityDefaulted,
    },
  };
}

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

function commandOutput(command: string[], input?: string, timeoutMs = 30_000): { ok: boolean; stdout: string; stderr: string; exitCode: number | null } {
  const result = spawnSync(command[0], command.slice(1), {
    cwd: repoRoot,
    input,
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 8,
    timeout: timeoutMs,
  });
  return {
    ok: result.status === 0,
    stdout: result.stdout ?? "",
    stderr: result.stderr ?? result.error?.message ?? "",
    exitCode: result.status,
  };
}

function runPsql(config: UniDeskConfig, sql: string): { ok: boolean; stdout: string; stderr: string; exitCode: number | null } {
  return commandOutput([
    "docker",
    "exec",
    "-i",
    "unidesk-database",
    "psql",
    "-v",
    "ON_ERROR_STOP=1",
    "-U",
    config.database.user,
    "-d",
    config.database.name,
    "-X",
    "-q",
    "-t",
    "-A",
  ], sql);
}

function ensureIdentityTableSql(): string {
  return `
CREATE TABLE IF NOT EXISTS unidesk_deploy_ssh_identities (
  id TEXT PRIMARY KEY,
  host TEXT NOT NULL,
  private_key TEXT NOT NULL,
  public_key TEXT NOT NULL,
  public_key_fingerprint TEXT NOT NULL DEFAULT '',
  known_hosts TEXT NOT NULL DEFAULT '',
  source TEXT NOT NULL DEFAULT 'operator-local',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
`;
}

function publicKeyFingerprint(publicKey: string): string {
  const parts = publicKey.trim().split(/\s+/u);
  const encoded = parts[1] ?? "";
  if (encoded.length === 0) return "";
  const digest = createHash("sha256").update(Buffer.from(encoded, "base64")).digest("base64").replace(/=+$/u, "");
  return `SHA256:${digest}`;
}

function githubKnownHostLinesFromText(text: string, hostName = "github.com"): string[] {
  const rows: string[] = [];
  const seen = new Set<string>();
  for (const rawLine of text.split(/\r?\n/u)) {
    const line = rawLine.trim();
    if (line.length === 0 || line.startsWith("#")) continue;
    const parts = line.split(/\s+/u);
    if (parts.length < 3) continue;
    const hostList = parts[0]?.split(",") ?? [];
    if (!hostList.some((host) => host === hostName || host === `[${hostName}]:22`)) continue;
    if (seen.has(line)) continue;
    seen.add(line);
    rows.push(line);
  }
  return rows;
}

function readGithubKnownHosts(knownHostsPath: string, host: string): string {
  const localLines = existsSync(knownHostsPath) ? githubKnownHostLinesFromText(readFileSync(knownHostsPath, "utf8"), host) : [];
  if (localLines.length > 0) return `${localLines.join("\n")}\n`;
  const scan = commandOutput(["ssh-keyscan", "-t", "rsa,ecdsa,ed25519", host], undefined, 20_000);
  const scannedLines = githubKnownHostLinesFromText(scan.stdout, host);
  if (scannedLines.length === 0) throw new Error(scan.stderr || `failed to collect ${host} SSH host keys`);
  return `${scannedLines.join("\n")}\n`;
}

function readLocalGithubIdentity(identity: DeploySshIdentitySpec): GithubSshIdentity | null {
  const local = identity.createFromLocal;
  if (local === null || !local.enabled) return null;
  const privateKeyPath = local.privateKeyPath;
  if (!existsSync(privateKeyPath)) return null;
  const privateKey = readFileSync(privateKeyPath, "utf8");
  if (!/-----BEGIN [A-Z ]*PRIVATE KEY-----/u.test(privateKey)) throw new Error(`invalid private key format: ${privateKeyPath}`);
  const publicKeyPath = local.publicKeyPath;
  const publicKey = existsSync(publicKeyPath)
    ? readFileSync(publicKeyPath, "utf8").trim()
    : commandOutput(["ssh-keygen", "-y", "-f", privateKeyPath]).stdout.trim();
  if (!/^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp256)\s+\S+/u.test(publicKey)) throw new Error(`invalid public key for ${privateKeyPath}`);
  return {
    privateKey: privateKey.endsWith("\n") ? privateKey : `${privateKey}\n`,
    publicKey,
    knownHosts: readGithubKnownHosts(local.knownHostsPath, identity.host),
    updatedAt: null,
  };
}

function writeSourceFileIfMissing(path: string, value: string, mode: number): boolean {
  if (existsSync(path)) return false;
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
  writeFileSync(path, value, { mode });
  chmodSync(path, mode);
  return true;
}

function ensureSourceGithubIdentity(config: DeploySshIdentityConfig, identitySpec: DeploySshIdentitySpec): SourceGithubIdentityResult {
  const paths = sourcePaths(config, identitySpec);
  let seededFromLocal = false;
  if (!existsSync(paths.privateKeyPath) || !existsSync(paths.publicKeyPath) || !existsSync(paths.knownHostsPath)) {
    const localIdentity = readLocalGithubIdentity(identitySpec);
    if (localIdentity !== null) {
      const seeded = [
        writeSourceFileIfMissing(paths.privateKeyPath, localIdentity.privateKey, 0o600),
        writeSourceFileIfMissing(paths.publicKeyPath, `${localIdentity.publicKey.trim()}\n`, 0o644),
        writeSourceFileIfMissing(paths.knownHostsPath, localIdentity.knownHosts, 0o600),
      ];
      seededFromLocal = seeded.some(Boolean);
    }
  }
  if (!existsSync(paths.privateKeyPath)) throw new Error(`${config.configPath}#identities.${identitySpec.id}.privateKey sourceRef is missing`);
  if (!existsSync(paths.publicKeyPath)) throw new Error(`${config.configPath}#identities.${identitySpec.id}.publicKey sourceRef is missing`);
  if (!existsSync(paths.knownHostsPath)) throw new Error(`${config.configPath}#identities.${identitySpec.id}.knownHosts sourceRef is missing`);
  const privateKey = readFileSync(paths.privateKeyPath, "utf8");
  const publicKey = readFileSync(paths.publicKeyPath, "utf8").trim();
  const knownHosts = readFileSync(paths.knownHostsPath, "utf8");
  if (!/-----BEGIN [A-Z ]*PRIVATE KEY-----/u.test(privateKey)) throw new Error(`${config.configPath}#identities.${identitySpec.id}.privateKey sourceRef has invalid private key material`);
  if (!/^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp256)\s+\S+/u.test(publicKey)) throw new Error(`${config.configPath}#identities.${identitySpec.id}.publicKey sourceRef has invalid public key material`);
  if (githubKnownHostLinesFromText(knownHosts, identitySpec.host).length === 0) throw new Error(`${config.configPath}#identities.${identitySpec.id}.knownHosts sourceRef has no ${identitySpec.host} rows`);
  const derived = commandOutput(["ssh-keygen", "-y", "-f", paths.privateKeyPath]);
  if (!derived.ok) throw new Error(`${config.configPath}#identities.${identitySpec.id}.privateKey failed ssh-keygen verification`);
  if (derived.stdout.trim() !== publicKey) throw new Error(`${config.configPath}#identities.${identitySpec.id}.privateKey does not match publicKey`);
  return {
    identity: {
      privateKey: privateKey.endsWith("\n") ? privateKey : `${privateKey}\n`,
      publicKey,
      knownHosts: knownHosts.endsWith("\n") ? knownHosts : `${knownHosts}\n`,
      updatedAt: null,
    },
    seededFromLocal,
  };
}

function upsertGithubIdentity(config: UniDeskConfig, identitySpec: DeploySshIdentitySpec, identity: GithubSshIdentity): void {
  const fingerprint = publicKeyFingerprint(identity.publicKey);
  const sql = `
${ensureIdentityTableSql()}
INSERT INTO unidesk_deploy_ssh_identities (id, host, private_key, public_key, public_key_fingerprint, known_hosts, source, updated_at)
VALUES (
  ${pgLiteral(identitySpec.id)},
  ${pgLiteral(identitySpec.host)},
  ${pgLiteral(identity.privateKey)},
  ${pgLiteral(identity.publicKey)},
  ${pgLiteral(fingerprint)},
  ${pgLiteral(identity.knownHosts)},
  ${pgLiteral(`${deploySshIdentitiesConfigPath}#identities.${identitySpec.id}`)},
  now()
)
ON CONFLICT (id) DO UPDATE SET
  host = EXCLUDED.host,
  private_key = EXCLUDED.private_key,
  public_key = EXCLUDED.public_key,
  public_key_fingerprint = EXCLUDED.public_key_fingerprint,
  known_hosts = EXCLUDED.known_hosts,
  source = EXCLUDED.source,
  updated_at = now();
`;
  const result = runPsql(config, sql);
  if (!result.ok) throw new Error(`failed to upsert GitHub SSH identity in PostgreSQL: ${result.stderr || `exit=${result.exitCode}`}`);
}

function readGithubIdentityFromDatabase(config: UniDeskConfig, identitySpec: DeploySshIdentitySpec): GithubSshIdentity {
  const sql = `
${ensureIdentityTableSql()}
SELECT json_build_object(
  'privateKey', private_key,
  'publicKey', public_key,
  'knownHosts', known_hosts,
  'updatedAt', updated_at
)::text
FROM unidesk_deploy_ssh_identities
WHERE id = ${pgLiteral(identitySpec.id)}
LIMIT 1;
`;
  const result = runPsql(config, sql);
  if (!result.ok) throw new Error(`failed to read GitHub SSH identity from PostgreSQL: ${result.stderr || `exit=${result.exitCode}`}`);
  const line = result.stdout.trim().split(/\r?\n/u).find((item) => item.trim().startsWith("{"));
  if (line === undefined) throw new Error("GitHub SSH identity is missing in PostgreSQL");
  const parsed = JSON.parse(line) as Partial<GithubSshIdentity>;
  const privateKey = typeof parsed.privateKey === "string" ? parsed.privateKey : "";
  const publicKey = typeof parsed.publicKey === "string" ? parsed.publicKey : "";
  const knownHosts = typeof parsed.knownHosts === "string" ? parsed.knownHosts : "";
  if (!/-----BEGIN [A-Z ]*PRIVATE KEY-----/u.test(privateKey)) throw new Error("PostgreSQL GitHub SSH identity has invalid private key material");
  if (!/^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp256)\s+\S+/u.test(publicKey)) throw new Error("PostgreSQL GitHub SSH identity has invalid public key material");
  if (githubKnownHostLinesFromText(knownHosts, identitySpec.host).length === 0) throw new Error(`PostgreSQL GitHub SSH identity has no ${identitySpec.host} known_hosts rows`);
  return {
    privateKey: privateKey.endsWith("\n") ? privateKey : `${privateKey}\n`,
    publicKey,
    knownHosts: knownHosts.endsWith("\n") ? knownHosts : `${knownHosts}\n`,
    updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : null,
  };
}

function remoteInstallPythonSource(): string {
  return String.raw`
import json
import os
import pathlib
import stat
import subprocess
import sys

data = json.load(sys.stdin)
home_dir = pathlib.Path(str(data.get("homeDir") or os.environ.get("HOME") or "/home/ubuntu"))
host = str(data.get("host") or "github.com")
ssh_dir = home_dir / ".ssh"
private_key = str(data.get("privateKey") or "")
public_key = str(data.get("publicKey") or "").strip()
known_hosts = str(data.get("knownHosts") or "")
home_stat = home_dir.stat()
owner_uid = home_stat.st_uid
owner_gid = home_stat.st_gid

def chown_to_home_owner(path):
    try:
        os.chown(path, owner_uid, owner_gid)
    except PermissionError:
        if os.geteuid() == 0:
            raise

if "PRIVATE KEY-----" not in private_key:
    raise SystemExit("invalid private key payload")
if not public_key.startswith(("ssh-ed25519 ", "ssh-rsa ", "ecdsa-sha2-nistp256 ")):
    raise SystemExit("invalid public key payload")

ssh_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
os.chmod(ssh_dir, 0o700)
chown_to_home_owner(ssh_dir)
private_path = ssh_dir / "id_ed25519"
public_path = ssh_dir / "id_ed25519.pub"
known_hosts_path = ssh_dir / "known_hosts"

private_path.write_text(private_key if private_key.endswith("\n") else private_key + "\n")
public_path.write_text(public_key + "\n")
os.chmod(private_path, stat.S_IRUSR | stat.S_IWUSR)
os.chmod(public_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
chown_to_home_owner(private_path)
chown_to_home_owner(public_path)

derived = subprocess.run(["ssh-keygen", "-y", "-f", str(private_path)], text=True, capture_output=True)
if derived.returncode != 0:
    raise SystemExit("installed private key failed ssh-keygen verification")
if derived.stdout.strip() != public_key:
    raise SystemExit("installed private key does not match public key")

known_hosts_path.touch(mode=0o600, exist_ok=True)
chown_to_home_owner(known_hosts_path)
subprocess.run(["ssh-keygen", "-R", host, "-f", str(known_hosts_path)], text=True, capture_output=True)
subprocess.run(["ssh-keygen", "-R", f"[{host}]:22", "-f", str(known_hosts_path)], text=True, capture_output=True)
existing = known_hosts_path.read_text().splitlines()
rows = []
seen = set()
for line in existing + known_hosts.splitlines():
    line = line.strip()
    if not line or line.startswith("#"):
        continue
    parts = line.split()
    if len(parts) < 3:
        continue
    if line in seen:
        continue
    seen.add(line)
    rows.append(line)
known_hosts_path.write_text("\n".join(rows) + "\n")
os.chmod(known_hosts_path, stat.S_IRUSR | stat.S_IWUSR)
chown_to_home_owner(known_hosts_path)
print(f"github_ssh_identity_written path={private_path} known_hosts_rows={len(rows)}")
`;
}

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

export function gitSshHttpConnectProxySource(): string {
  return String.raw`#!/usr/bin/env python3
import os
import select
import socket
import sys
from urllib.parse import urlparse

if len(sys.argv) != 3:
    raise SystemExit("usage: unidesk-git-ssh-http-connect.py host port")

target_host = sys.argv[1]
target_port = int(sys.argv[2])
proxy = urlparse(os.environ.get("UNIDESK_GIT_SSH_HTTP_PROXY", "http://127.0.0.1:18789"))
proxy_host = proxy.hostname or "127.0.0.1"
proxy_port = proxy.port or 80

sock = socket.create_connection((proxy_host, proxy_port), timeout=20)
sock.sendall(f"CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n".encode("ascii"))
header = b""
while b"\r\n\r\n" not in header:
    chunk = sock.recv(4096)
    if not chunk:
        raise SystemExit("proxy closed before CONNECT response")
    header += chunk
head, rest = header.split(b"\r\n\r\n", 1)
if not (head.startswith(b"HTTP/1.1 200") or head.startswith(b"HTTP/1.0 200")):
    sys.stderr.write(head.decode("latin1", "replace") + "\n")
    raise SystemExit(1)
if rest:
    os.write(1, rest)

stdin_open = True
sock.setblocking(False)
while True:
    readers = [sock]
    if stdin_open:
        readers.append(sys.stdin.buffer)
    ready, _, _ = select.select(readers, [], [])
    if sock in ready:
        try:
            data = sock.recv(65536)
        except BlockingIOError:
            data = b""
        if not data:
            break
        os.write(1, data)
    if stdin_open and sys.stdin.buffer in ready:
        data = os.read(0, 65536)
        if data:
            sock.sendall(data)
        else:
            stdin_open = False
            try:
                sock.shutdown(socket.SHUT_WR)
            except OSError:
                pass
`;
}

async function distributeGithubIdentity(config: UniDeskConfig, target: DeploySshTargetSpec, identitySpec: DeploySshIdentitySpec, identity: GithubSshIdentity): Promise<{ ok: boolean; detail: string; raw: unknown }> {
  const payload = JSON.stringify({
    privateKey: identity.privateKey,
    publicKey: identity.publicKey,
    knownHosts: identity.knownHosts,
    homeDir: target.homeDir,
    host: identitySpec.host,
  });
  const remotePython = remoteInstallPythonSource();
  const proxyPython = gitSshHttpConnectProxySource();
  const remoteCommand = [
    "set -euo pipefail",
    `python3 -c ${shellQuote(remotePython)}`,
    `home_dir=${shellQuote(target.homeDir)}`,
    "export HOME=\"$home_dir\"",
    `host=${shellQuote(identitySpec.host)}`,
    `egress_mode=${shellQuote(target.egress.mode)}`,
    `proxy_url=${target.egress.mode === "http-connect-proxy" ? shellQuote(target.egress.proxyUrl) : "''"}`,
    "ssh_dir=\"$HOME/.ssh\"",
    "git_ssh_proxy=\"$ssh_dir/unidesk-git-ssh-http-connect.py\"",
    "ssh_config=\"$ssh_dir/config\"",
    "if [ \"$egress_mode\" = \"http-connect-proxy\" ]; then",
    "  curl -fsSL --max-time 20 -x \"$proxy_url\" \"https://$host\" -o /dev/null",
    "else",
    "  curl -fsSL --max-time 20 \"https://$host\" -o /dev/null",
    "fi",
    "tmp_config=$(mktemp)",
    "touch \"$ssh_config\"",
    "chmod 600 \"$ssh_config\"",
    "awk '/^# BEGIN unidesk managed github-ssh-identity$/{skip=1; next} /^# END unidesk managed github-ssh-identity$/{skip=0; next} !skip{print}' \"$ssh_config\" > \"$tmp_config\"",
    "if [ \"$egress_mode\" = \"http-connect-proxy\" ]; then",
    "  cat > \"$git_ssh_proxy\" <<'UNIDESK_GIT_SSH_PROXY'",
    proxyPython,
    "UNIDESK_GIT_SSH_PROXY",
    "  chmod 700 \"$git_ssh_proxy\"",
    "  {",
    "    printf '%s\\n' '# BEGIN unidesk managed github-ssh-identity'",
    "    printf 'Host %s\\n' \"$host\"",
    "    printf '  HostName %s\\n' \"$host\"",
    "    printf '%s\\n' '  User git'",
    "    printf '  IdentityFile %s/.ssh/id_ed25519\\n' \"$HOME\"",
    "    printf '%s\\n' '  IdentitiesOnly yes'",
    "    printf '%s\\n' '  BatchMode yes'",
    "    printf '%s\\n' '  StrictHostKeyChecking yes'",
    "    printf '  UserKnownHostsFile %s/.ssh/known_hosts\\n' \"$HOME\"",
    "    printf '  ProxyCommand env UNIDESK_GIT_SSH_HTTP_PROXY=%s %s %%h %%p\\n' \"$proxy_url\" \"$git_ssh_proxy\"",
    "    printf '%s\\n' '# END unidesk managed github-ssh-identity'",
    "    cat \"$tmp_config\"",
    "  } > \"$ssh_config\"",
    "else",
    "  {",
    "    printf '%s\\n' '# BEGIN unidesk managed github-ssh-identity'",
    "    printf 'Host %s\\n' \"$host\"",
    "    printf '  HostName %s\\n' \"$host\"",
    "    printf '%s\\n' '  User git'",
    "    printf '  IdentityFile %s/.ssh/id_ed25519\\n' \"$HOME\"",
    "    printf '%s\\n' '  IdentitiesOnly yes'",
    "    printf '%s\\n' '  BatchMode yes'",
    "    printf '%s\\n' '  StrictHostKeyChecking yes'",
    "    printf '  UserKnownHostsFile %s/.ssh/known_hosts\\n' \"$HOME\"",
    "    printf '%s\\n' '# END unidesk managed github-ssh-identity'",
    "    cat \"$tmp_config\"",
    "  } > \"$ssh_config\"",
    "fi",
    "rm -f \"$tmp_config\"",
    "chmod 600 \"$ssh_config\"",
    "auth_output=$(ssh -F \"$ssh_config\" -T \"git@$host\" 2>&1 || true)",
    "printf '%s\\n' \"$auth_output\"",
    "printf '%s\\n' \"$auth_output\" | grep -q 'successfully authenticated'",
  ].join("\n");
  const result = await runSshCommandCapture(config, target.route, ["argv", "bash", "-lc", remoteCommand], payload);
  const stdout = result.stdout ?? "";
  const stderr = result.stderr ?? "";
  return {
    ok: result.exitCode === 0,
    detail: [stdout, stderr].filter(Boolean).join("\n").slice(-2000),
    raw: {
      targetId: target.targetId,
      providerId: target.providerId,
      route: target.route,
      homeDir: target.homeDir,
      egress: target.egress,
      identityId: identitySpec.id,
      host: identitySpec.host,
      exitCode: result.exitCode,
      stdoutTail: stdout.slice(-1200),
      stderrTail: stderr.slice(-1200),
      valuesRedacted: true,
    },
  };
}

function deploySshIdentitySourceStatus(config: DeploySshIdentityConfig, identity: DeploySshIdentitySpec): Record<string, unknown> {
  const paths = sourcePaths(config, identity);
  const sourceStatus = (kind: string, sourceRef: string, path: string): Record<string, unknown> => {
    const present = existsSync(path);
    return {
      kind,
      sourceRef,
      sourceKey: "file",
      present,
      bytes: present ? statSync(path).size : 0,
    };
  };
  const publicKey = existsSync(paths.publicKeyPath) ? readFileSync(paths.publicKeyPath, "utf8").trim() : "";
  return {
    privateKey: sourceStatus("privateKey", identity.privateKey.sourceRef, paths.privateKeyPath),
    publicKey: {
      ...sourceStatus("publicKey", identity.publicKey.sourceRef, paths.publicKeyPath),
      fingerprint: publicKey.length > 0 ? publicKeyFingerprint(publicKey) : null,
    },
    knownHosts: {
      ...sourceStatus("knownHosts", identity.knownHosts.sourceRef, paths.knownHostsPath),
      hostRows: existsSync(paths.knownHostsPath) ? githubKnownHostLinesFromText(readFileSync(paths.knownHostsPath, "utf8"), identity.host).length : 0,
    },
  };
}

export function deploySshIdentityPlan(targetSelection: string | null | undefined, identitySelection: string | null | undefined = null): Record<string, unknown> {
  const deployConfig = loadDeploySshIdentityConfig();
  const { target, defaulted: targetDefaulted } = selectDeploySshTarget(deployConfig, targetSelection);
  const { identity, defaulted: identityDefaulted } = selectDeploySshIdentity(deployConfig, target, identitySelection);
  const sourceStatus = deploySshIdentitySourceStatus(deployConfig, identity);
  const allSourcesPresent = [sourceStatus.privateKey, sourceStatus.publicKey, sourceStatus.knownHosts].every((item) => asRecord(item, "sourceStatus").present === true);
  return {
    ok: true,
    action: "deploy-ssh-identity-plan",
    mutation: false,
    identity: {
      id: identity.id,
      host: identity.host,
      sourceStatus,
      createFromLocal: identity.createFromLocal === null ? null : {
        enabled: identity.createFromLocal.enabled,
        privateKeyPath: identity.createFromLocal.privateKeyPath,
        publicKeyPath: identity.createFromLocal.publicKeyPath,
        knownHostsPath: identity.createFromLocal.knownHostsPath,
      },
    },
    target: {
      targetId: target.targetId,
      providerId: target.providerId,
      route: target.route,
      homeDir: target.homeDir,
      egress: target.egress,
    },
    ready: allSourcesPresent || identity.createFromLocal?.enabled === true,
    configTruth: configTruth(deployConfig, target, identity, targetDefaulted, identityDefaulted),
    valuesRedacted: true,
    next: {
      ensure: `bun scripts/cli.ts ci github-ssh-identity ensure --target ${target.targetId} --identity ${identity.id} --confirm`,
    },
  };
}

export async function ensureGithubSshIdentityForProvider(config: UniDeskConfig, providerId: string, identitySelection: string | null | undefined = null): Promise<GithubSshIdentityDistribution> {
  const deployConfig = loadDeploySshIdentityConfig();
  const { target, defaulted: targetDefaulted } = selectDeploySshTarget(deployConfig, providerId);
  const { identity: identitySpec, defaulted: identityDefaulted } = selectDeploySshIdentity(deployConfig, target, identitySelection);
  const source = ensureSourceGithubIdentity(deployConfig, identitySpec);
  upsertGithubIdentity(config, identitySpec, source.identity);
  const identity = readGithubIdentityFromDatabase(config, identitySpec);
  const fingerprint = publicKeyFingerprint(identity.publicKey);
  const distribution = await distributeGithubIdentity(config, target, identitySpec, identity);
  if (!distribution.ok) {
    return {
      ok: false,
      detail: `failed to distribute GitHub SSH identity from YAML sourceRef via PostgreSQL to ${target.targetId}: ${distribution.detail || "remote ssh failed"}`,
      fingerprint,
      seededFromLocal: source.seededFromLocal,
      identityId: identitySpec.id,
      targetId: target.targetId,
      configTruth: configTruth(deployConfig, target, identitySpec, targetDefaulted, identityDefaulted),
      raw: distribution.raw,
    };
  }
  return {
    ok: true,
    detail: `GitHub SSH identity distributed from YAML sourceRef via PostgreSQL to ${target.targetId}; fingerprint=${fingerprint}; seededFromLocal=${source.seededFromLocal}`,
    fingerprint,
    seededFromLocal: source.seededFromLocal,
    identityId: identitySpec.id,
    targetId: target.targetId,
    configTruth: configTruth(deployConfig, target, identitySpec, targetDefaulted, identityDefaulted),
    raw: distribution.raw,
  };
}
