import { existsSync, readFileSync } from "node:fs";
import { isAbsolute, join } from "node:path";
import { rootPath } from "./config";

const hostK8sConfigPath = "config/unidesk-host-k8s.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 stringField(obj: Record<string, unknown>, key: string, path: string): string {
  const value = obj[key];
  if (typeof value !== "string" || value.length === 0) throw new Error(`${path}.${key} must be a non-empty string`);
  return value;
}

function readEnvFile(path: string): Record<string, string> {
  const values: Record<string, string> = {};
  const text = readFileSync(path, "utf8");
  for (const [index, rawLine] of text.split(/\r?\n/u).entries()) {
    const line = rawLine.trim();
    if (line.length === 0 || line.startsWith("#")) continue;
    const eq = line.indexOf("=");
    if (eq <= 0) throw new Error(`${path}:${index + 1} must be KEY=value`);
    values[line.slice(0, eq)] = line.slice(eq + 1);
  }
  return values;
}

function readHostK8sConfig(): Record<string, unknown> | null {
  const path = rootPath(hostK8sConfigPath);
  if (!existsSync(path)) return null;
  return asRecord(Bun.YAML.parse(readFileSync(path, "utf8")) as unknown, hostK8sConfigPath);
}

export function readHostK8sPublicHost(): string | null {
  const config = readHostK8sConfig();
  if (config === null) return null;
  const runtime = asRecord(config.runtime, `${hostK8sConfigPath}.runtime`);
  return stringField(runtime, "publicHost", `${hostK8sConfigPath}.runtime`);
}

export function readHostK8sSshClientToken(): string | null {
  const config = readHostK8sConfig();
  if (config === null) return null;
  const runtimeSecrets = asRecord(config.runtimeSecrets, `${hostK8sConfigPath}.runtimeSecrets`);
  const sourceRef = asRecord(runtimeSecrets.sourceRef, `${hostK8sConfigPath}.runtimeSecrets.sourceRef`);
  const target = asRecord(runtimeSecrets.target, `${hostK8sConfigPath}.runtimeSecrets.target`);
  const keys = asRecord(target.keys, `${hostK8sConfigPath}.runtimeSecrets.target.keys`);
  const sourcePathRaw = stringField(sourceRef, "path", `${hostK8sConfigPath}.runtimeSecrets.sourceRef`);
  const tokenKey = stringField(keys, "sshClientToken", `${hostK8sConfigPath}.runtimeSecrets.target.keys`);
  const sourcePath = isAbsolute(sourcePathRaw) ? sourcePathRaw : join(rootPath(), sourcePathRaw);
  if (!existsSync(sourcePath)) return null;
  const token = readEnvFile(sourcePath)[tokenKey]?.trim() ?? "";
  return token.length > 0 ? token : null;
}
