import { describe, expect, it } from "vitest";
import { CLI_COMMANDS, VALID_FLAGS } from "../src/cli/args";
import onboardingMetadata from "../src/cli/onboarding-metadata.json";
import {
  INSPIREDESIGN_HANDOFF_COMMANDS,
  INSPIREDESIGN_HANDOFF_GUIDANCE
} from "../src/inspiredesign/handoff";
import {
  COMMAND_HELP_DETAILS,
  HELP_CAPABILITY_ENTRIES,
  HELP_COMMAND_GROUPS,
  HELP_FLAG_GROUPS,
  HELP_ONBOARDING_ENTRIES,
  HELP_REFERENCE_ENTRIES,
  HELP_TOOL_ENTRIES,
  getCliOnlyCommands,
  getHelpText,
  getToolOnlyHelperNames
} from "../src/cli/help";

describe("CLI help surface", () => {
  it("covers every CLI command exactly once", () => {
    const seen = new Set<string>();

    for (const group of HELP_COMMAND_GROUPS) {
      for (const command of group.commands) {
        expect(seen.has(command), `${command} should not repeat`).toBe(false);
        seen.add(command);
        expect(COMMAND_HELP_DETAILS[command].usage.length).toBeGreaterThan(0);
      }
    }

    expect(seen.size).toBe(CLI_COMMANDS.length);
    for (const command of CLI_COMMANDS) {
      expect(seen.has(command), `${command} should be included`).toBe(true);
    }
  });

  it("covers every CLI flag exactly once", () => {
    const seen = new Set<string>();

    for (const group of HELP_FLAG_GROUPS) {
      for (const entry of group.flags) {
        expect(seen.has(entry.flag), `${entry.flag} should not repeat`).toBe(false);
        seen.add(entry.flag);
      }
    }

    expect(seen.size).toBe(VALID_FLAGS.length);
    for (const flag of VALID_FLAGS) {
      expect(seen.has(flag), `${flag} should be included`).toBe(true);
    }
  });

  it("lists every tool exactly once", () => {
    const seen = new Set<string>();

    for (const entry of HELP_TOOL_ENTRIES) {
      expect(entry.name.startsWith("opendevbrowser_")).toBe(true);
      expect(seen.has(entry.name), `${entry.name} should not repeat`).toBe(false);
      seen.add(entry.name);
    }

    expect(seen.size).toBe(HELP_TOOL_ENTRIES.length);
  });

  it("defines an explicit onboarding block for first-contact agents", () => {
    const labels = HELP_ONBOARDING_ENTRIES.map((entry) => entry.label);

    expect(labels).toEqual([
      "prompting_guide",
      "skill_load",
      "validated_lanes",
      "skill_list",
      "research_evidence_gated",
      "shopping_reliable",
      "inspiredesign_followthrough",
      "computer_use_entry",
      "happy_path",
      "surface_split",
      "docs"
    ]);
    expect(HELP_ONBOARDING_ENTRIES[0]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.promptingGuide);
    expect(HELP_ONBOARDING_ENTRIES[1]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.skillLoad);
    expect(HELP_ONBOARDING_ENTRIES[2]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.validatedLanes);
    expect(HELP_ONBOARDING_ENTRIES[2]?.details).toHaveLength(1);
    expect(HELP_ONBOARDING_ENTRIES[3]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.skillList);
    expect(HELP_ONBOARDING_ENTRIES[4]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.validatedResearch);
    expect(HELP_ONBOARDING_ENTRIES[5]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.validatedShopping);
    expect(HELP_ONBOARDING_ENTRIES[6]?.details).toEqual([
      { label: "quick:", value: INSPIREDESIGN_HANDOFF_COMMANDS.loadBestPractices },
      { label: "design:", value: INSPIREDESIGN_HANDOFF_COMMANDS.loadDesignAgent },
      { label: "motion:", value: INSPIREDESIGN_HANDOFF_COMMANDS.loadMotionDesign },
      { label: "brief:", value: INSPIREDESIGN_HANDOFF_GUIDANCE.reviewAdvancedBrief },
      { label: "gate:", value: "Require nextStepGuidance.readiness=ready and no matching doNotProceedIf blockers before Canvas continuation." },
      { label: "prep:", value: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest },
      { label: "run:", value: INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas }
    ]);
    expect(HELP_ONBOARDING_ENTRIES[7]?.details?.[0]?.value).toBe(onboardingMetadata.quickStartCommands.computerUseEntry);
    expect(HELP_ONBOARDING_ENTRIES[9]?.details).toEqual([
      { label: "cli-only:", value: getCliOnlyCommands().join(", ") },
      { label: "tool-only:", value: getToolOnlyHelperNames().join(", ") }
    ]);
    expect(HELP_ONBOARDING_ENTRIES[10]?.details).toHaveLength(1);
  });

  it("defines explicit find-it-fast lookup entries for replay, desktop observation, and browser-scoped computer use", () => {
    const labels = HELP_CAPABILITY_ENTRIES.map((entry) => entry.label);

    expect(labels).toEqual([
      "screencast / browser replay",
      "desktop observation",
      "computer use / browser-scoped computer use"
    ]);
    expect(HELP_CAPABILITY_ENTRIES[0]?.details?.[0]?.value).toBe("screencast-start, screencast-stop");
    expect(HELP_CAPABILITY_ENTRIES[0]?.details?.[1]?.value).toContain("screencast-start --session-id <id>");
    expect(HELP_CAPABILITY_ENTRIES[1]?.details?.[0]?.value).toContain("desktop-status");
    expect(HELP_CAPABILITY_ENTRIES[1]?.details?.[1]?.value).toBe("npx opendevbrowser desktop-status --output-format json");
    expect(HELP_CAPABILITY_ENTRIES[1]?.description).toContain("swift command");
    expect(HELP_CAPABILITY_ENTRIES[1]?.description).toContain("screencapture");
    expect(HELP_CAPABILITY_ENTRIES[2]?.details?.[0]?.value).toBe("--challenge-automation-mode off|browser|browser_with_helper");
    expect(HELP_CAPABILITY_ENTRIES[2]?.details?.[1]?.value).toContain("macro-resolve --execute");
    expect(HELP_CAPABILITY_ENTRIES[2]?.details?.[2]?.value).toBe(onboardingMetadata.quickStartCommands.computerUseEntry);
    expect(HELP_CAPABILITY_ENTRIES[2]?.description).toContain("not a desktop agent");
  });

  it("prints complete command, flag, and tool inventories with descriptions", () => {
    const output = getHelpText();

    expect(output).toContain(`${onboardingMetadata.sectionTitle}:`);
    expect(output).toContain(onboardingMetadata.sectionSummary);
    expect(output).toContain(onboardingMetadata.quickStartCommands.promptingGuide);
    expect(output).toContain(onboardingMetadata.quickStartCommands.skillLoad);
    expect(output).toContain(onboardingMetadata.quickStartCommands.validatedLanes);
    expect(output).toContain(onboardingMetadata.quickStartCommands.skillList);
    expect(output).toContain(onboardingMetadata.quickStartCommands.validatedResearch);
    expect(output).toContain(onboardingMetadata.quickStartCommands.validatedShopping);
    expect(output).toContain(INSPIREDESIGN_HANDOFF_COMMANDS.loadBestPractices);
    expect(output).toContain(INSPIREDESIGN_HANDOFF_COMMANDS.loadDesignAgent);
    expect(output).toContain(INSPIREDESIGN_HANDOFF_COMMANDS.loadMotionDesign);
    expect(output).toContain(INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest);
    expect(output).toContain(INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas);
    expect(output).toContain(onboardingMetadata.quickStartCommands.computerUseEntry);
    expect(output).toContain(onboardingMetadata.quickStartCommands.happyPath);
    expect(output).toContain("research_evidence_gated");
    expect(output).not.toContain("research_reliable");
    expect(output).not.toContain("Generic topical research is currently safest");
    expect(output).not.toContain("--source-selection auto");
    expect(output).toContain("inspect artifacts before final claims");
    expect(output).toContain(getCliOnlyCommands().join(", "));
    expect(output).toContain(getToolOnlyHelperNames().join(", "));
    expect(output).toContain(onboardingMetadata.referencePaths.onboardingDoc);
    expect(output).toContain(onboardingMetadata.referencePaths.skillDoc);
    expect(output).toContain("Find It Fast:");
    expect(output).toContain("Use these exact lookup terms when you need replay, desktop evidence, or browser-scoped computer use.");
    expect(output).toContain("screencast / browser replay");
    expect(output).toContain("desktop observation");
    expect(output).toContain("computer use / browser-scoped computer use");
    expect(output).toContain("screencast-start, screencast-stop");
    expect(output).toContain("desktop-status, desktop-windows");
    expect(output).toContain("swift command");
    expect(output).toContain("screencapture");
    expect(output).toContain("--challenge-automation-mode off|browser|browser_with_helper");
    expect(output).toContain("research run, shopping run, product-video run, inspiredesign run, inspiredesign harvest, macro-resolve --execute");
    expect(output).toContain(onboardingMetadata.quickStartCommands.computerUseEntry);
    expect(output).toContain("not a desktop agent");
    expect(output).toContain("surface_split");
    expect(output).toContain(`Command Inventory (all ${CLI_COMMANDS.length} commands):`);
    expect(output).toContain("Flag Inventory (all supported flags):");
    expect(output).toContain(`Tool Inventory (all ${HELP_TOOL_ENTRIES.length} opendevbrowser_* tools):`);

    for (const command of CLI_COMMANDS) {
      expect(output).toContain(command);
      expect(output).toContain(COMMAND_HELP_DETAILS[command].description);
      expect(output).toContain(COMMAND_HELP_DETAILS[command].usage);
    }

    for (const flag of VALID_FLAGS) {
      expect(output).toContain(flag);
    }

    for (const tool of HELP_TOOL_ENTRIES) {
      expect(output).toContain(tool.name);
      expect(output).toContain(tool.description);
    }

    expect(output).toContain("usage:");
    expect(output).toContain("flags:");
    expect(output).toContain("example:");
    expect(output).toContain("cli:");
    expect(output).toContain("docs/SURFACE_REFERENCE.md");
    expect(output).toContain("docs/WORKFLOW_SURFACE_MAP.md");
    expect(output).toContain("src/tools/index.ts");
    expect(output).toContain("src/cli/help.ts");
    expect(output).toContain("src/providers/workflow-handoff.ts");
    expect(output).toContain("src/inspiredesign/handoff.ts");
    expect(output).toContain("src/public-surface/generated-manifest.ts");
    expect(output).toContain(COMMAND_HELP_DETAILS.inspiredesign.examples[0]);
    expect(output).toContain(COMMAND_HELP_DETAILS.inspiredesign.examples[1]);
    expect(output).toContain(HELP_TOOL_ENTRIES.find((entry) => entry.name === "opendevbrowser_skill_load")?.example ?? "");
    expect(output).not.toContain("src/tools/surface.ts");
  });

  it("keeps workflow surface map in the reference pointers", () => {
    const labels = HELP_REFERENCE_ENTRIES.map((entry) => entry.label);

    expect(labels).toContain("docs/WORKFLOW_SURFACE_MAP.md");
  });
});
