const fs = require("fs");
const path = require("path");
const { resolveOrchestration } = require("./orchestration");
const { disabledSet, overlayParseError } = require("./disabled-skills");
const { buildExplanation } = require("./explanation");
const { matchKeywords } = require("./intent-parser");
const { defaultConfirmOverride } = require("./env-flags");
const { detectWorkspaceBoundary } = require("./workspace-boundary");

function resolveInstallationStatus(routeResult, rootDir) {
  const winner = routeResult.winner;
  if (!winner) {
    return { resolution_status: "installed", resolution_hint: null };
  }

  const disabled = rootDir ? disabledSet(rootDir) : new Set();

  if (winner.type === "skill") {
    if (disabled.has(winner.resource)) {
      return {
        resolution_status: "not_installed",
        resolution_hint: `Skill "${winner.resource}" disabled — run capint skill enable ${winner.resource}`
      };
    }
    const allSkills = routeResult.rows.flatMap((r) => r.skills);
    const match = allSkills.find((s) => s.name === winner.resource);
    if (match?.status === "not_installed" || match?.status === "disabled") {
      return {
        resolution_status: "not_installed",
        resolution_hint:
          match?.status === "disabled"
            ? `Skill "${winner.resource}" disabled — run capint skill enable ${winner.resource}`
            : `Skill "${winner.resource}" not installed — run capint init or add skills/${winner.resource}/SKILL.md`
      };
    }
  }

  if (winner.type === "workflow" && rootDir) {
    const wfPath = path.join(rootDir, "workflows", `${winner.resource}.md`);
    if (!fs.existsSync(wfPath)) {
      return {
        resolution_status: "not_installed",
        resolution_hint: `Workflow "${winner.resource}" missing — run capint init to copy skill bundle`
      };
    }
  }

  return { resolution_status: "installed", resolution_hint: null };
}

function buildConfirmBlock(text, overallWeight, matrix) {
  const policy = matrix?.clarification_policy || {};
  const mode = policy.mode || "adaptive";
  const shouldAsk = mode === "always_confirm" || overallWeight !== "light";
  if (!shouldAsk) return { enabled: false, mode, prompt: null, options: [], default_option: null };

  const options = [
    { id: "apply_now", label: "Apply now" },
    { id: "plan_first", label: "Show short plan first" },
    { id: "analyze_only", label: "Analyze only, no code" }
  ];
  const maxOptions = Math.max(1, Math.min(policy.max_options || 3, options.length));
  const shortened = options.slice(0, maxOptions);
  let defaultOption = policy.default_option || (overallWeight === "light" ? "apply_now" : "plan_first");
  const envDefault = defaultConfirmOverride();
  if (envDefault && shortened.some((o) => o.id === envDefault)) {
    defaultOption = envDefault;
  }
  return {
    enabled: true,
    mode,
    prompt: `How should I proceed? (${text.slice(0, 80)}${text.length > 80 ? "..." : ""})`,
    options: shortened,
    default_option: shortened.some((o) => o.id === defaultOption) ? defaultOption : shortened[0].id
  };
}

function buildVerificationHints(overallWeight, primaryTaskType, matrix) {
  const defaults = matrix?.verification_defaults || {};
  const profile = primaryTaskType?.verification_profile || defaults.profile || "standard";
  const taskRequires = Boolean(primaryTaskType?.verification_required);

  if (overallWeight === "light" && !defaults.require_on_light && !taskRequires) {
    return { required: false, hints: [], profile };
  }

  const hints = [];
  hints.push("Run a targeted test or lint command before claiming done");
  if (profile === "security") {
    hints.push("Verify auth/session paths and no secret leakage");
  } else if (profile === "debug") {
    hints.push("Reproduce bug, apply fix, re-run failing case");
  } else if (profile === "refactor") {
    hints.push("Existing tests pass; no behavior change unless intended");
  }

  const required =
    overallWeight === "heavy" ||
    overallWeight === "medium" ||
    Boolean(primaryTaskType?.verification_required);

  return { required, hints, profile };
}

function buildRouteExplain(routeResult, parsedIntent, matrix) {
  const primary = routeResult.taskTypeResolved;
  return {
    matched_task_type: primary?.id || null,
    resolver_order: matrix?.resolver_order || [],
    winner: routeResult.winner
      ? { name: routeResult.winner.name, resource: routeResult.winner.resource, confidence: routeResult.confidence }
      : null,
    overrides: parsedIntent?.overrides || {},
    overall_weight: routeResult.overall
  };
}

function buildExecutionPolicy({ rawText, routeResult, memoryStrategy, matrix, parsedIntent, rootDir }) {
  const primaryTaskType = routeResult.taskTypeResolved;
  const rows = routeResult.rows;
  const overallWeight = routeResult.overall;
  const fallbackCapability =
    matrix?.fallback_policy?.ambiguous_default_capability || primaryTaskType?.id || "vague_request";
  const capability = primaryTaskType?.capability || fallbackCapability;
  const installStatus = resolveInstallationStatus(routeResult, rootDir);
  let plan =
    primaryTaskType?.default_execution_policy ||
    matrix?.execution_policy_defaults?.[overallWeight] ||
    (overallWeight === "light" ? "auto" : "confirm");
  if (installStatus.resolution_status === "not_installed") {
    plan = "confirm";
  }
  const boundary = detectWorkspaceBoundary(rawText);
  const overlayCorrupt = rootDir ? overlayParseError(rootDir) : false;
  let confirmBlock = buildConfirmBlock(rawText, overallWeight, matrix);
  if (!confirmBlock.enabled) {
    plan = "auto";
  }
  if (boundary.violated) {
    plan = "override";
    confirmBlock = {
      enabled: false,
      mode: "blocked",
      prompt: null,
      options: [],
      default_option: null
    };
  }
  const ambiguous = rows.some((r) => r.reason.includes("ambiguous default"));
  const verification = buildVerificationHints(overallWeight, primaryTaskType, matrix);
  const orchestration = resolveOrchestration(primaryTaskType, confirmBlock.default_option, matrix);

  const explanation = buildExplanation({
    text: rawText,
    routeResult,
    matrix,
    rootDir,
    matchKeywords,
    resolutionStatus: installStatus.resolution_status,
    confirmDefaultOption: confirmBlock.default_option
  });

  const out = {
    intent: rawText,
    capability,
    resolution: `${routeResult.winner.name}/${routeResult.winner.resource}`,
    memory: memoryStrategy?.memory || primaryTaskType?.requires_memory || "optional",
    plan,
    confirm: confirmBlock,
    confirm_question: confirmBlock.prompt,
    confirm_options: confirmBlock.options,
    confirm_default_option: confirmBlock.default_option,
    fallback: ambiguous ? { capability, override: matrix?.fallback_policy?.override_hint || "/workflow" } : null,
    verification_required: verification.required,
    verification_hints: verification.hints,
    verification_profile: verification.profile,
    provider_activation: memoryStrategy?.provider_activation || null,
    context_pack: memoryStrategy?.context_pack || null,
    orchestration,
    route_explain: buildRouteExplain(routeResult, parsedIntent, matrix),
    explanation,
    resolution_status: installStatus.resolution_status,
    resolution_hint: installStatus.resolution_hint
  };

  if (memoryStrategy?.local_adapters) {
    out.local_adapters = memoryStrategy.local_adapters;
  }

  if (confirmBlock.default_option === "analyze_only" && verification.required) {
    out.verification_hints = [
      ...verification.hints,
      "analyze_only: produce evidence-backed findings without code edits"
    ];
  }

  if (installStatus.resolution_status === "not_installed") {
    out.verification_required = true;
    out.verification_hints = [
      ...(out.verification_hints || []),
      "install skill bundle or add SKILL.md before apply"
    ];
  }

  if (boundary.violated) {
    out.workspace_boundary = {
      violated: true,
      suspicious_paths: boundary.suspicious_paths,
      override_hint: boundary.override_hint
    };
    out.verification_required = true;
    out.verification_hints = [
      ...(out.verification_hints || []),
      "Refuse file edits outside workspace until user adds cross-repo override phrase"
    ];
  }

  if (overlayCorrupt) {
    out.overlay_error = {
      file: ".capint/disabled-skills.json",
      hint: "Fix or remove corrupt disabled-skills overlay — routing fail-closed until repaired"
    };
    out.resolution_status = "not_installed";
    out.resolution_hint =
      "Corrupt .capint/disabled-skills.json — fix JSON or remove file, then capint doctor";
    out.verification_required = true;
    out.verification_hints = [
      ...(out.verification_hints || []),
      "disabled-skills overlay corrupt; all skills treated as disabled until fixed"
    ];
  }

  return out;
}

module.exports = {
  buildExecutionPolicy,
  buildConfirmBlock,
  buildVerificationHints,
  buildRouteExplain,
  resolveInstallationStatus
};
