import { formatEther } from "viem";
import type { AgentConfig } from "./config.js";
import { createChainClients } from "./chain.js";
import { PONS_FACTORY, PONS_LOCKER, ponsFactoryAbi } from "./contracts.js";

export type DoctorCheck = {
  name: string;
  status: "pass" | "warn" | "fail";
  detail: string;
};

export const runDoctor = async (config: AgentConfig): Promise<DoctorCheck[]> => {
  const checks: DoctorCheck[] = [];
  const { publicClient } = createChainClients(config);

  try {
    const chainId = await publicClient.getChainId();
    checks.push({ name: "Robinhood Chain", status: chainId === 4663 ? "pass" : "fail", detail: `chainId ${chainId}` });
  } catch (error) {
    return [{ name: "Robinhood RPC", status: "fail", detail: error instanceof Error ? error.message : "RPC unavailable" }];
  }

  const [code, launchEnabled, launchFee, locker] = await Promise.all([
    publicClient.getCode({ address: PONS_FACTORY }),
    publicClient.readContract({ address: PONS_FACTORY, abi: ponsFactoryAbi, functionName: "launchEnabled" }),
    publicClient.readContract({ address: PONS_FACTORY, abi: ponsFactoryAbi, functionName: "launchFee" }),
    publicClient.readContract({ address: PONS_FACTORY, abi: ponsFactoryAbi, functionName: "locker" }),
  ]);

  checks.push({ name: "Pons factory", status: code && code !== "0x" ? "pass" : "fail", detail: PONS_FACTORY });
  checks.push({ name: "Pons launches", status: launchEnabled ? "pass" : "fail", detail: launchEnabled ? "enabled" : "disabled" });
  checks.push({
    name: "Pons launch fee",
    status: launchFee <= config.maxLaunchTotalWei ? "pass" : "fail",
    detail: `${formatEther(launchFee)} ETH · configured launch ceiling ${formatEther(config.maxLaunchTotalWei)} ETH`,
  });
  checks.push({ name: "Pons locker", status: locker.toLowerCase() === PONS_LOCKER.toLowerCase() ? "pass" : "fail", detail: locker });

  if (config.account) {
    const balance = await publicClient.getBalance({ address: config.account.address });
    const required = launchFee + config.minGasReserveWei;
    checks.push({
      name: "Execution wallet",
      status: balance >= required ? "pass" : "warn",
      detail: `${config.account.address} · ${formatEther(balance)} ETH`,
    });
  } else {
    checks.push({ name: "Execution wallet", status: config.mode === "live" ? "fail" : "warn", detail: "not configured (observe mode only)" });
  }

  if (config.mode === "live" && config.autoBuybackEnabled && config.account && config.feeWallet
    && config.account.address.toLowerCase() !== config.feeWallet.toLowerCase()) {
    checks.push({
      name: "Buyback fee wallet",
      status: "fail",
      detail: "FEE_WALLET must match the execution wallet when automatic buyback is enabled",
    });
  }

  checks.push({ name: "xAPI", status: config.xApi.key ? "pass" : "warn", detail: config.xApi.key ? "configured" : "missing key" });
  checks.push({
    name: "5.6sol gateway",
    status: config.model.baseUrl && config.model.apiKey && config.model.name ? "pass" : "warn",
    detail: config.model.baseUrl && config.model.apiKey && config.model.name ? config.model.name : "incomplete configuration",
  });
  checks.push({ name: "Execution mode", status: config.mode === "live" ? "warn" : "pass", detail: config.mode });

  return checks;
};
