import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
import { CLAUDE_AGENTS_DIR, SETTINGS_FILE, CCJK_SKILLS_DIR } from '../chunks/constants.mjs';
import { j as join } from './ccjk.bQ7Dh1g4.mjs';
import { memoryCheck } from '../chunks/memory-check.mjs';
import process__default from 'node:process';

const agentsCheck = {
  name: "Agents",
  weight: 4,
  async check() {
    try {
      if (!existsSync(CLAUDE_AGENTS_DIR)) {
        return {
          name: this.name,
          status: "warn",
          score: 30,
          weight: this.weight,
          message: "No agents directory",
          fix: "Create agents for specialized tasks",
          command: "ccjk agents"
        };
      }
      const files = readdirSync(CLAUDE_AGENTS_DIR).filter((f) => f.endsWith(".md"));
      const agentCount = files.length;
      if (agentCount === 0) {
        return {
          name: this.name,
          status: "warn",
          score: 30,
          weight: this.weight,
          message: "No agents configured",
          fix: "Create agents for your project",
          command: "ccjk agents"
        };
      }
      const score = Math.min(100, 40 + agentCount * 15);
      return {
        name: this.name,
        status: score >= 60 ? "pass" : "warn",
        score,
        weight: this.weight,
        message: `${agentCount} agent${agentCount > 1 ? "s" : ""} configured`,
        details: files.slice(0, 5).map((f) => `  ${f.replace(".md", "")}`)
      };
    } catch {
      return { name: this.name, status: "fail", score: 0, weight: this.weight, message: "Failed to read agents" };
    }
  }
};

const claudeMdCheck = {
  name: "CLAUDE.md",
  weight: 7,
  async check() {
    const cwd = process.cwd();
    const claudeMdPath = join(cwd, "CLAUDE.md");
    try {
      if (!existsSync(claudeMdPath)) {
        return {
          name: this.name,
          status: "fail",
          score: 0,
          weight: this.weight,
          message: "No CLAUDE.md in project root",
          fix: "Create CLAUDE.md for project-specific AI instructions",
          command: "ccjk init --smart"
        };
      }
      const stat = statSync(claudeMdPath);
      const content = readFileSync(claudeMdPath, "utf-8");
      const lines = content.split("\n").length;
      const sizeKb = Math.round(stat.size / 1024);
      const hasHeaders = (content.match(/^#{1,3}\s/gm) || []).length;
      const hasCodeBlocks = (content.match(/```/g) || []).length / 2;
      const hasBuildCommands = /build|test|lint|dev/i.test(content);
      let score = 40;
      if (lines > 20)
        score += 15;
      if (hasHeaders >= 3)
        score += 15;
      if (hasCodeBlocks >= 1)
        score += 10;
      if (hasBuildCommands)
        score += 20;
      score = Math.min(100, score);
      return {
        name: this.name,
        status: score >= 60 ? "pass" : "warn",
        score,
        weight: this.weight,
        message: `${lines} lines, ${sizeKb}KB`,
        details: [
          `  Sections: ${hasHeaders}`,
          `  Code blocks: ${Math.floor(hasCodeBlocks)}`,
          `  Build info: ${hasBuildCommands ? "yes" : "no"}`
        ],
        ...score < 80 && { fix: "Enrich CLAUDE.md with more project context", command: "ccjk init --smart" }
      };
    } catch {
      return { name: this.name, status: "fail", score: 0, weight: this.weight, message: "Failed to read CLAUDE.md" };
    }
  }
};

const mcpCheck = {
  name: "MCP Services",
  weight: 8,
  async check() {
    try {
      if (!existsSync(SETTINGS_FILE)) {
        return {
          name: this.name,
          status: "fail",
          score: 0,
          weight: this.weight,
          message: "No settings.json found",
          fix: "Run ccjk init to create settings",
          command: "ccjk init"
        };
      }
      const settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
      const mcpServers = settings.mcpServers || {};
      const serverCount = Object.keys(mcpServers).length;
      if (serverCount === 0) {
        return {
          name: this.name,
          status: "fail",
          score: 0,
          weight: this.weight,
          message: "No MCP services configured",
          fix: "Install MCP services for enhanced capabilities",
          command: "ccjk mcp"
        };
      }
      const essentialServices = ["context7"];
      const hasEssentials = essentialServices.filter(
        (s) => Object.keys(mcpServers).some((k) => k.toLowerCase().includes(s))
      );
      const score = Math.min(100, serverCount * 20 + hasEssentials.length * 20);
      const status = score >= 60 ? "pass" : "warn";
      const details = Object.keys(mcpServers).map((name) => `  ${name}`);
      return {
        name: this.name,
        status,
        score,
        weight: this.weight,
        message: `${serverCount} service${serverCount > 1 ? "s" : ""} active`,
        details,
        ...score < 80 && { fix: "Add more MCP services", command: "ccjk mcp" }
      };
    } catch {
      return {
        name: this.name,
        status: "fail",
        score: 0,
        weight: this.weight,
        message: "Failed to read MCP configuration",
        command: "ccjk doctor"
      };
    }
  }
};

function collectModelDetails(settings) {
  const env = settings?.env || {};
  const details = [];
  const primaryModel = settings?.model && settings.model !== "default" ? settings.model : env.ANTHROPIC_MODEL;
  const haikuModel = env.ANTHROPIC_DEFAULT_HAIKU_MODEL || env.ANTHROPIC_SMALL_FAST_MODEL;
  const sonnetModel = env.ANTHROPIC_DEFAULT_SONNET_MODEL;
  const opusModel = env.ANTHROPIC_DEFAULT_OPUS_MODEL;
  if (primaryModel) {
    details.push(`  primary: ${primaryModel}`);
  }
  if (haikuModel) {
    details.push(`  haiku: ${haikuModel}`);
  }
  if (sonnetModel) {
    details.push(`  sonnet: ${sonnetModel}`);
  }
  if (opusModel) {
    details.push(`  opus: ${opusModel}`);
  }
  return details;
}
const modelCheck = {
  name: "Default Model",
  weight: 5,
  async check() {
    try {
      if (!existsSync(SETTINGS_FILE)) {
        return {
          name: this.name,
          status: "fail",
          score: 0,
          weight: this.weight,
          message: "No settings file",
          command: "ccjk init"
        };
      }
      const settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
      const hasModel = settings.model || settings.env?.ANTHROPIC_MODEL || settings.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL || settings.env?.ANTHROPIC_SMALL_FAST_MODEL || settings.env?.ANTHROPIC_DEFAULT_SONNET_MODEL || settings.env?.ANTHROPIC_DEFAULT_OPUS_MODEL;
      const hasCredential = settings.authToken || settings.apiKey || settings.env?.ANTHROPIC_AUTH_TOKEN || settings.env?.ANTHROPIC_API_KEY || process__default.env.ANTHROPIC_AUTH_TOKEN || process__default.env.ANTHROPIC_API_KEY;
      const details = collectModelDetails(settings);
      if (!hasCredential) {
        return {
          name: this.name,
          status: "warn",
          score: 40,
          weight: this.weight,
          message: "No API key configured (using default)",
          fix: "Configure API for direct access",
          command: "ccjk menu",
          details: details.length > 0 ? details : ["  Using Claude Code default API"]
        };
      }
      return {
        name: this.name,
        status: "pass",
        score: hasModel ? 100 : 70,
        weight: this.weight,
        message: hasModel ? `Model configured` : "API configured (default model)",
        details
      };
    } catch {
      return { name: this.name, status: "fail", score: 0, weight: this.weight, message: "Failed to read model config" };
    }
  }
};

const INVALID_PERMISSION_NAMES = /* @__PURE__ */ new Set([
  "AllowEdit",
  "AllowWrite",
  "AllowRead",
  "AllowExec",
  "AllowCreateProcess",
  "AllowKillProcess",
  "AllowNetworkAccess",
  "AllowFileSystemAccess",
  "AllowShellAccess",
  "AllowHttpAccess"
]);
function isValidPermission(perm) {
  if (INVALID_PERMISSION_NAMES.has(perm))
    return false;
  if (["mcp__.*", "mcp__*", "mcp__(*)"].includes(perm))
    return false;
  return true;
}
const permissionsCheck = {
  name: "Permissions",
  weight: 3,
  async check() {
    try {
      if (!existsSync(SETTINGS_FILE)) {
        return {
          name: this.name,
          status: "warn",
          score: 30,
          weight: this.weight,
          message: "No settings file",
          command: "ccjk init"
        };
      }
      const settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
      const allowedTools = settings.permissions?.allow || [];
      if (allowedTools.length === 0) {
        return {
          name: this.name,
          status: "warn",
          score: 40,
          weight: this.weight,
          message: "No tool permissions configured",
          fix: "Configure permissions to reduce prompts",
          command: "ccjk menu"
        };
      }
      const invalidPerms = allowedTools.filter((p) => !isValidPermission(p));
      const validPerms = allowedTools.filter((p) => isValidPermission(p));
      if (invalidPerms.length > 0) {
        return {
          name: this.name,
          status: "warn",
          score: 50,
          weight: this.weight,
          message: `${invalidPerms.length} invalid permission(s) found (${validPerms.length} valid)`,
          fix: "Run ccjk init to repair permissions",
          command: "ccjk init"
        };
      }
      const score = Math.min(100, 60 + validPerms.length * 2);
      return {
        name: this.name,
        status: "pass",
        score,
        weight: this.weight,
        message: `${validPerms.length} valid permission${validPerms.length > 1 ? "s" : ""} configured`
      };
    } catch {
      return { name: this.name, status: "fail", score: 0, weight: this.weight, message: "Failed to read permissions" };
    }
  }
};

const skillsCheck = {
  name: "Skills",
  weight: 6,
  async check() {
    try {
      if (!existsSync(CCJK_SKILLS_DIR)) {
        return {
          name: this.name,
          status: "warn",
          score: 20,
          weight: this.weight,
          message: "No skills directory found",
          fix: "Install skills to enhance Claude Code",
          command: "ccjk skills"
        };
      }
      const files = readdirSync(CCJK_SKILLS_DIR).filter((f) => f.endsWith(".md"));
      const skillCount = files.length;
      if (skillCount === 0) {
        return {
          name: this.name,
          status: "warn",
          score: 20,
          weight: this.weight,
          message: "No skills installed",
          fix: "Install skills based on your project",
          command: "ccjk skills"
        };
      }
      const score = Math.min(100, 30 + skillCount * 10);
      return {
        name: this.name,
        status: score >= 60 ? "pass" : "warn",
        score,
        weight: this.weight,
        message: `${skillCount} skill${skillCount > 1 ? "s" : ""} installed`,
        details: files.slice(0, 8).map((f) => `  ${f.replace(".md", "")}`),
        ...skillCount < 5 && { fix: "Install more project-specific skills", command: "ccjk skills" }
      };
    } catch {
      return { name: this.name, status: "fail", score: 0, weight: this.weight, message: "Failed to read skills" };
    }
  }
};

const DEFAULT_CHECKS = [
  mcpCheck,
  skillsCheck,
  claudeMdCheck,
  modelCheck,
  agentsCheck,
  permissionsCheck,
  memoryCheck
];
function calculateGrade(score) {
  if (score >= 95)
    return "S";
  if (score >= 80)
    return "A";
  if (score >= 65)
    return "B";
  if (score >= 50)
    return "C";
  if (score >= 30)
    return "D";
  return "F";
}
function generateRecommendations(results) {
  const recs = [];
  for (const r of results) {
    if (r.status === "fail" && r.command) {
      recs.push({
        priority: "high",
        title: `Fix: ${r.name}`,
        description: r.fix || r.message,
        command: r.command,
        category: mapCategory(r.name)
      });
    } else if (r.status === "warn" && r.command) {
      recs.push({
        priority: "medium",
        title: `Improve: ${r.name}`,
        description: r.fix || r.message,
        command: r.command,
        category: mapCategory(r.name)
      });
    }
  }
  const priorityOrder = { high: 0, medium: 1, low: 2 };
  recs.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
  return recs;
}
function mapCategory(name) {
  const lower = name.toLowerCase();
  if (lower.includes("mcp"))
    return "mcp";
  if (lower.includes("skill"))
    return "skills";
  if (lower.includes("agent"))
    return "agents";
  if (lower.includes("model") || lower.includes("api"))
    return "model";
  if (lower.includes("memory"))
    return "sync";
  if (lower.includes("sync"))
    return "sync";
  if (lower.includes("perm"))
    return "permissions";
  return "general";
}
async function runHealthCheck(checks) {
  const activeChecks = checks || DEFAULT_CHECKS;
  const results = [];
  const promises = activeChecks.map(async (check) => {
    try {
      return await check.check();
    } catch {
      return {
        name: check.name,
        status: "fail",
        score: 0,
        weight: check.weight,
        message: "Check failed unexpectedly"
      };
    }
  });
  const settled = await Promise.all(promises);
  results.push(...settled);
  const totalWeight = results.reduce((sum, r) => sum + r.weight, 0);
  const weightedSum = results.reduce((sum, r) => sum + r.score * r.weight, 0);
  const totalScore = totalWeight > 0 ? Math.round(weightedSum / totalWeight) : 0;
  return {
    totalScore,
    grade: calculateGrade(totalScore),
    results,
    recommendations: generateRecommendations(results),
    timestamp: Date.now()
  };
}

export { runHealthCheck as r };
