/**
 * Environment test for the DeepSeek (via Hermes) adapter.
 */

import { execFile } from "node:child_process";
import { promisify } from "node:util";
import fs from "node:fs/promises";
import path from "node:path";
import {
  HERMES_CLI,
  ADAPTER_TYPE,
  DEFAULT_PROFILE_HOME,
} from "../shared/constants.js";

const execFileAsync = promisify(execFile);

function asString(v) {
  return typeof v === "string" ? v : undefined;
}

async function checkCliInstalled(command) {
  try {
    await execFileAsync(command, ["--version"], { timeout: 10_000 });
    return null;
  } catch (err) {
    if (err && err.code === "ENOENT") {
      return {
        level: "error",
        message: `Hermes CLI "${command}" not found in PATH`,
        hint: "Install Hermes Agent: pip install hermes-agent",
        code: "deepseek_hermes_cli_not_found",
      };
    }
    return null;
  }
}

async function checkProfile(profileHome) {
  try {
    const stat = await fs.stat(profileHome);
    if (!stat.isDirectory()) {
      return {
        level: "error",
        message: `Profile path is not a directory: ${profileHome}`,
        hint: "Create the directory or override hermesProfileHome in adapter config.",
        code: "deepseek_profile_not_dir",
      };
    }
  } catch {
    return {
      level: "error",
      message: `Hermes profile dir does not exist: ${profileHome}`,
      hint: "Create the profile dir with config.yaml + .env (DEEPSEEK_API_KEY).",
      code: "deepseek_profile_missing",
    };
  }

  const configPath = path.join(profileHome, "config.yaml");
  try {
    await fs.stat(configPath);
  } catch {
    return {
      level: "error",
      message: `Profile is missing config.yaml: ${configPath}`,
      hint: "Add config.yaml with model.default + model.base_url + model.key_env.",
      code: "deepseek_profile_no_config",
    };
  }

  return {
    level: "info",
    message: `Profile resolved: ${profileHome}`,
    code: "deepseek_profile_ok",
  };
}

async function checkApiKey(profileHome, configEnv) {
  // 1. config.env (resolved by Paperclip from secrets)
  if (configEnv && typeof configEnv === "object" && asString(configEnv.DEEPSEEK_API_KEY)) {
    return {
      level: "info",
      message: "DEEPSEEK_API_KEY found in adapter env config",
      code: "deepseek_api_key_in_config",
    };
  }
  // 2. Profile-local .env
  try {
    const envFile = path.join(profileHome, ".env");
    const text = await fs.readFile(envFile, "utf-8");
    if (/^\s*DEEPSEEK_API_KEY=/m.test(text)) {
      return {
        level: "info",
        message: `DEEPSEEK_API_KEY found in ${envFile}`,
        code: "deepseek_api_key_in_profile",
      };
    }
  } catch {
    // ignore
  }
  // 3. Process env
  if (process.env.DEEPSEEK_API_KEY) {
    return {
      level: "info",
      message: "DEEPSEEK_API_KEY found in Paperclip process env",
      code: "deepseek_api_key_in_process",
    };
  }
  return {
    level: "error",
    message: "DEEPSEEK_API_KEY not found in adapter env, profile .env, or process env",
    hint: "Add DEEPSEEK_API_KEY to <HERMES_HOME>/.env or to the agent's env secrets.",
    code: "deepseek_api_key_missing",
  };
}

export async function testEnvironment(ctx) {
  const config = ctx.config ?? {};
  const command = asString(config.hermesCommand) || HERMES_CLI;
  const profileHome = asString(config.hermesProfileHome) || DEFAULT_PROFILE_HOME;
  const checks = [];

  const cliCheck = await checkCliInstalled(command);
  if (cliCheck) {
    checks.push(cliCheck);
    if (cliCheck.level === "error") {
      return {
        adapterType: ADAPTER_TYPE,
        status: "fail",
        checks,
        testedAt: new Date().toISOString(),
      };
    }
  }

  const profileCheck = await checkProfile(profileHome);
  checks.push(profileCheck);
  if (profileCheck.level === "error") {
    return {
      adapterType: ADAPTER_TYPE,
      status: "fail",
      checks,
      testedAt: new Date().toISOString(),
    };
  }

  const apiKeyCheck = await checkApiKey(profileHome, config.env);
  checks.push(apiKeyCheck);

  const model = asString(config.model);
  checks.push({
    level: "info",
    message: model ? `Model: ${model}` : "Using profile default model",
    code: "deepseek_model",
  });

  const hasErrors = checks.some((c) => c.level === "error");
  const hasWarnings = checks.some((c) => c.level === "warn");
  return {
    adapterType: ADAPTER_TYPE,
    status: hasErrors ? "fail" : hasWarnings ? "warn" : "pass",
    checks,
    testedAt: new Date().toISOString(),
  };
}
