// @vitest-environment happy-dom
// Pure prop-driven component, but match the act() convention used by
// the other ClaimDrawer test files (ClaimDrawerHeader /
// ClaimDrawerSkeleton / ClaimDrawerError).
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;

import React, { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { describe, expect, it } from "vitest";
import { ValidationPanel } from "./ValidationPanel";
import type { ClaimDetailValidation, ClaimDetailValidationIssue } from "@/types";

function renderIntoContainer(element: React.ReactElement): {
  container: HTMLDivElement;
  unmount: () => void;
} {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const root: Root = createRoot(container);
  act(() => {
    root.render(element);
  });
  return {
    container,
    unmount: () => {
      act(() => root.unmount());
      container.remove();
    },
  };
}

function makeIssue(
  overrides: Partial<ClaimDetailValidationIssue> = {}
): ClaimDetailValidationIssue {
  return {
    rule: "R050_diagnosis_present",
    message: "Primary diagnosis is required",
    severity: "error",
    ...overrides,
  };
}

function makeValidation(
  overrides: Partial<ClaimDetailValidation> = {}
): ClaimDetailValidation {
  return {
    passed: true,
    errors: [],
    warnings: [],
    ...overrides,
  };
}

describe("ValidationPanel", () => {
  it("test_all_passed_state_renders_checkmark_and_message", () => {
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel validation={makeValidation({ passed: true })} />
    );

    // The pass-state root has data-testid="validation-passed".
    const passedRoot = container.querySelector('[data-testid="validation-passed"]');
    expect(passedRoot).not.toBeNull();

    // The success copy is in the rendered text.
    const text = (container.textContent ?? "").toLowerCase();
    expect(text).toContain("all checks passed");

    // The checkmark icon (lucide-react `CheckCircle2`) is an inline SVG.
    const svg = passedRoot?.querySelector("svg");
    expect(svg).not.toBeNull();

    // Neither sub-section is rendered when nothing is wrong.
    expect(container.querySelector('[data-testid="validation-errors"]')).toBeNull();
    expect(container.querySelector('[data-testid="validation-warnings"]')).toBeNull();

    unmount();
  });

  it("test_errors_only_renders_errors_subsection", () => {
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel
        validation={makeValidation({
          passed: false,
          errors: [
            makeIssue({
              rule: "R050_diagnosis_present",
              message: "Primary diagnosis is required",
              severity: "error",
            }),
          ],
        })}
      />
    );

    const errorsBlock = container.querySelector('[data-testid="validation-errors"]');
    expect(errorsBlock).not.toBeNull();

    // Red left-border token applied to the inner block — sniff the className.
    const cls = errorsBlock?.className ?? "";
    expect(cls).toContain("border-[color:var(--m-error)]");
    expect(cls).toContain("border-l-2");

    // Rule code + message visible in the rendered text.
    const text = container.textContent ?? "";
    expect(text).toContain("R050_diagnosis_present");
    expect(text).toContain("Primary diagnosis is required");

    // No warnings sub-section when only errors are present.
    expect(container.querySelector('[data-testid="validation-warnings"]')).toBeNull();
    // And no all-passed pill.
    expect(container.querySelector('[data-testid="validation-passed"]')).toBeNull();

    unmount();
  });

  it("test_warnings_only_renders_warnings_subsection", () => {
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel
        validation={makeValidation({
          passed: true,
          warnings: [
            makeIssue({
              rule: "R200_units_recommended",
              message: "Units reported as 0",
              severity: "warning",
            }),
          ],
        })}
      />
    );

    const warningsBlock = container.querySelector('[data-testid="validation-warnings"]');
    expect(warningsBlock).not.toBeNull();

    // Amber left-border token applied to the inner block.
    const cls = warningsBlock?.className ?? "";
    expect(cls).toContain("border-[color:var(--m-warning)]");
    expect(cls).toContain("border-l-2");

    const text = container.textContent ?? "";
    expect(text).toContain("R200_units_recommended");
    expect(text).toContain("Units reported as 0");

    // No errors sub-section when only warnings are present.
    expect(container.querySelector('[data-testid="validation-errors"]')).toBeNull();

    unmount();
  });

  it("test_both_errors_and_warnings_renders_both", () => {
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel
        validation={makeValidation({
          passed: false,
          errors: [
            makeIssue({
              rule: "R050_diagnosis_present",
              message: "Primary diagnosis is required",
            }),
          ],
          warnings: [
            makeIssue({
              rule: "R200_units_recommended",
              message: "Units reported as 0",
              severity: "warning",
            }),
          ],
        })}
      />
    );

    expect(container.querySelector('[data-testid="validation-errors"]')).not.toBeNull();
    expect(container.querySelector('[data-testid="validation-warnings"]')).not.toBeNull();

    // Errors sub-section appears before warnings sub-section (blocking
    // issues first, then advisories).
    const errorsEl = container.querySelector('[data-testid="validation-errors"]');
    const warningsEl = container.querySelector('[data-testid="validation-warnings"]');
    expect(errorsEl).not.toBeNull();
    expect(warningsEl).not.toBeNull();
    expect(
      errorsEl!.compareDocumentPosition(warningsEl!) & Node.DOCUMENT_POSITION_FOLLOWING
    ).toBeTruthy();

    unmount();
  });

  it("test_errors_are_grouped_by_rule_with_count", () => {
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel
        validation={makeValidation({
          passed: false,
          errors: [
            makeIssue({
              rule: "R050_diagnosis_present",
              message: "Primary diagnosis is required",
            }),
            makeIssue({
              rule: "R050_diagnosis_present",
              message: "Diagnosis qualifier is required",
            }),
          ],
        })}
      />
    );

    const errorsBlock = container.querySelector('[data-testid="validation-errors"]');
    expect(errorsBlock).not.toBeNull();

    const text = errorsBlock?.textContent ?? "";

    // Header should show the rule code with the grouped count "(2)".
    expect(text).toContain("R050_diagnosis_present");
    expect(text).toContain("(2)");

    // Both messages appear underneath the group header.
    expect(text).toContain("Primary diagnosis is required");
    expect(text).toContain("Diagnosis qualifier is required");

    unmount();
  });

  it("test_passed_with_warnings_still_shows_warnings", () => {
    // The "all checks passed" pill is reserved for passed && no-warnings;
    // passed=true with warnings present should still surface the warnings
    // sub-section so the user notices the advisories.
    const { container, unmount } = renderIntoContainer(
      <ValidationPanel
        validation={makeValidation({
          passed: true,
          warnings: [
            makeIssue({
              rule: "R200_units_recommended",
              message: "Units reported as 0",
              severity: "warning",
            }),
          ],
        })}
      />
    );

    expect(container.querySelector('[data-testid="validation-warnings"]')).not.toBeNull();
    expect(container.querySelector('[data-testid="validation-passed"]')).toBeNull();

    unmount();
  });
});
