import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { axe } from "vitest-axe";

import { PromotionCard } from "../";

/**
 * PromotionCard Component Conformance Tests
 *
 * These tests verify the complete functionality of the PromotionCard component including:
 *
 * 🎯 HTML VALIDITY
 * - HTML validity with various prop combinations
 * - Semantic HTML structure
 * - Complex JSX structure validation
 * - Card wrapper structure
 *
 * ♿ ACCESSIBILITY (A11y)
 * - WCAG 2.1 compliance checks
 * - Proper use of semantic HTML elements
 * - ARIA attributes and their validity
 * - Interactive elements (buttons, links)
 * - Focus management and keyboard navigation
 * - Screen reader compatibility
 * - Color contrast compliance
 *
 * 🎨 FUNCTIONAL BEHAVIOR
 * - Correct application of CSS classes (promotion-card, card)
 * - Color scheme variants: light (default), dark
 * - Color mapping to Card component (background-primary, background-contrast)
 * - Custom className merging
 * - Props combinations
 * - Card integration and structure
 * - Text inverse functionality for dark color scheme
 *
 * 📝 CONTENT RENDERING
 * - Text children rendering through Card
 * - Complex JSX children
 * - Multiple children
 * - Empty content handling
 *
 * ⚠️ EDGE CASES
 * - Null, undefined, boolean children
 * - Number and array children
 * - Invalid props graceful handling
 * - Boundary usage cases
 *
 * 🔗 INTEGRATION TESTS
 * - Working with interactive elements
 * - Card component integration
 * - Event handling
 * - Focus management
 */

describe("PromotionCard Component Conformance Tests", () => {
  describe("HTML Validity", () => {
    it("is valid HTML with default props", () => {
      const { container } = render(<PromotionCard />);
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with all props", () => {
      const { container } = render(
        <PromotionCard
          color="background-contrast"
          className="test-class"
          data-testid="test-promotion-card"
        >
          <h2>Promotion Title</h2>
          <p>Promotion description</p>
        </PromotionCard>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with complex content", () => {
      const { container } = render(
        <PromotionCard>
          <header>
            <h1>Special Offer</h1>
          </header>
          <main>
            <section>
              <h2>Details</h2>
              <p>Limited time promotion</p>
              <button type="button">Learn More</button>
            </section>
          </main>
        </PromotionCard>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with Card wrapper", () => {
      const { container } = render(
        <PromotionCard>
          <div>Content wrapped in Card</div>
        </PromotionCard>,
      );
      expect(container).toHTMLValidate();
    });
  });

  describe("Accessibility", () => {
    it("is accessible with default props", async () => {
      const { container } = render(<PromotionCard />);
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with light color scheme", async () => {
      const { container } = render(
        <PromotionCard color="background-primary">
          <h1>Light Theme Promotion</h1>
          <p>This is a light themed promotion card.</p>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with dark color scheme", async () => {
      const { container } = render(
        <PromotionCard color="background-contrast">
          <h1>Dark Theme Promotion</h1>
          <p>This is a dark themed promotion card with proper contrast.</p>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with complex content", async () => {
      const { container } = render(
        <PromotionCard color="background-primary">
          <header>
            <h1>Promotion Title</h1>
            <nav aria-label="Promotion navigation">
              <ul>
                <li>
                  <a href="#details">Details</a>
                </li>
                <li>
                  <a href="#terms">Terms</a>
                </li>
              </ul>
            </nav>
          </header>
          <main>
            <section>
              <h2>Offer Details</h2>
              <p>
                Get <strong>50% off</strong> on all items this week.
              </p>
              <button type="button" aria-describedby="offer-description">
                Claim Offer
              </button>
              <p id="offer-description">Click to claim your discount code</p>
            </section>
          </main>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with interactive elements", async () => {
      const { container } = render(
        <PromotionCard>
          <form>
            <label htmlFor="email">Email for special offers</label>
            <input
              type="email"
              id="email"
              name="email"
              aria-describedby="email-help"
            />
            <p id="email-help">We&apos;ll send you exclusive deals</p>
            <button type="submit">Subscribe</button>
          </form>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with ARIA attributes", async () => {
      const { container } = render(
        <PromotionCard
          role="region"
          aria-label="Special promotion offer"
          aria-describedby="promotion-description"
        >
          <h2>Flash Sale</h2>
          <p id="promotion-description">Limited time offer ending soon</p>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with Card wrapper", async () => {
      const { container } = render(
        <PromotionCard>
          <div role="article">
            <h1>Accessible promotion content</h1>
          </div>
        </PromotionCard>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });
  });

  describe("Functional Behavior", () => {
    it("renders with correct default classes", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card" />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveClass("card");
      expect(card).toHaveClass("promotion-card");
      expect(card).not.toHaveClass("background-primary");
    });

    it("applies color scheme classes correctly", () => {
      const colors = ["background-primary", "background-contrast"];
      colors.forEach((color) => {
        const { container } = render(
          <PromotionCard color={color} data-testid="test-promotion-card" />,
        );
        const card = container.querySelector(
          '[data-testid="test-promotion-card"]',
        );

        expect(card).toHaveClass("promotion-card");

        if (color === "background-primary") {
          expect(card).not.toHaveClass("background-primary");
          expect(card).not.toHaveClass("background-contrast");
          expect(card).not.toHaveClass("text-inverse");
        } else {
          expect(card).toHaveClass("background-contrast");
          expect(card).toHaveClass("text-inverse");
        }
      });
    });

    it("applies dark color scheme with text-inverse correctly", () => {
      const { container } = render(
        <PromotionCard
          color="background-contrast"
          data-testid="test-promotion-card"
        />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveClass("promotion-card");
      expect(card).toHaveClass("background-contrast");
      expect(card).toHaveClass("text-inverse");
    });

    it("combines multiple props correctly", () => {
      const { container } = render(
        <PromotionCard
          color="background-contrast"
          className="custom-class"
          data-testid="test-promotion-card"
        />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveClass("card");
      expect(card).toHaveClass("promotion-card");
      expect(card).toHaveClass("background-contrast");
      expect(card).toHaveClass("text-inverse");
      expect(card).toHaveClass("custom-class");
    });

    it("passes through additional props", () => {
      const { container } = render(
        <PromotionCard
          data-testid="test-promotion-card"
          id="promotion-id"
          role="region"
          aria-label="Special offer"
        />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveAttribute("id", "promotion-id");
      expect(card).toHaveAttribute("role", "region");
      expect(card).toHaveAttribute("aria-label", "Special offer");
    });

    it("integrates properly with Card component", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card" noBorder={true}>
          <div>Card content</div>
        </PromotionCard>,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveClass("card");
      expect(card).toHaveClass("promotion-card");
      expect(card).toHaveClass("card--no-border");
    });
  });

  describe("Content Rendering", () => {
    it("renders text children through Card", () => {
      render(<PromotionCard>Simple promotion text</PromotionCard>);
      expect(screen.getByText("Simple promotion text")).toBeInTheDocument();
    });

    it("renders complex JSX children through Card", () => {
      render(
        <PromotionCard>
          <header>
            <h1>Promotion Header</h1>
            <nav aria-label="Promotion navigation">
              <ul>
                <li>
                  <a href="#offer">Offer</a>
                </li>
                <li>
                  <a href="#terms">Terms</a>
                </li>
              </ul>
            </nav>
          </header>
          <main>
            <article>
              <h2>Special Deal</h2>
              <p>
                Save big with our <strong>exclusive offer</strong>.
              </p>
            </article>
          </main>
        </PromotionCard>,
      );

      expect(screen.getByText("Promotion Header")).toBeInTheDocument();
      expect(screen.getByText("Offer")).toBeInTheDocument();
      expect(screen.getByText("Terms")).toBeInTheDocument();
      expect(screen.getByText("Special Deal")).toBeInTheDocument();
      expect(screen.getByText(/Save big with our/)).toBeInTheDocument();
      expect(screen.getByText("exclusive offer")).toBeInTheDocument();
    });

    it("renders multiple children through Card", () => {
      render(
        <PromotionCard>
          <div>Section 1</div>
          <div>Section 2</div>
          <div>Section 3</div>
        </PromotionCard>,
      );

      expect(screen.getByText("Section 1")).toBeInTheDocument();
      expect(screen.getByText("Section 2")).toBeInTheDocument();
      expect(screen.getByText("Section 3")).toBeInTheDocument();
    });

    it("renders empty children", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card" />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toBeInTheDocument();
      expect(card.children.length).toBe(0);
    });

    it("renders Card with proper structure", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card">
          <p>Test content</p>
        </PromotionCard>,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toBeInTheDocument();
      expect(card).toHaveClass("card");
      expect(card).toHaveClass("promotion-card");
      expect(card).toContainElement(screen.getByText("Test content"));
    });
  });

  describe("Edge Cases", () => {
    it("handles null children", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card">{null}</PromotionCard>,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toBeInTheDocument();
    });

    it("handles undefined children", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card">
          {undefined}
        </PromotionCard>,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toBeInTheDocument();
    });

    it("handles boolean children", () => {
      const { container } = render(
        <PromotionCard data-testid="test-promotion-card">{true}</PromotionCard>,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toBeInTheDocument();
    });

    it("handles number children", () => {
      render(<PromotionCard>42</PromotionCard>);
      expect(screen.getByText("42")).toBeInTheDocument();
    });

    it("handles array children", () => {
      render(
        <PromotionCard>{["Promo 1", "Promo 2", "Promo 3"]}</PromotionCard>,
      );
      expect(screen.getByText(/Promo 1/)).toBeInTheDocument();
      expect(screen.getByText(/Promo 2/)).toBeInTheDocument();
      expect(screen.getByText(/Promo 3/)).toBeInTheDocument();
    });

    it("handles invalid color prop gracefully", () => {
      const { container } = render(
        <PromotionCard
          color="invalid-color"
          data-testid="test-promotion-card"
        />,
      );
      const card = container.querySelector(
        '[data-testid="test-promotion-card"]',
      );
      expect(card).toHaveClass("promotion-card");
      // Should render with custom color if provided
      expect(card).toHaveClass("invalid-color");
    });
  });

  describe("Integration Tests", () => {
    it("works with interactive elements", async () => {
      const user = userEvent.setup();
      const handleClick = vi.fn();

      render(
        <PromotionCard>
          <button type="button" onClick={handleClick}>
            Claim Offer
          </button>
          <input type="text" placeholder="Enter code" />
          <select>
            <option value="offer1">Offer 1</option>
            <option value="offer2">Offer 2</option>
          </select>
        </PromotionCard>,
      );

      const button = screen.getByRole("button", { name: "Claim Offer" });
      const input = screen.getByPlaceholderText("Enter code");
      const select = screen.getByRole("combobox");

      expect(button).toBeInTheDocument();
      expect(input).toBeInTheDocument();
      expect(select).toBeInTheDocument();

      await user.click(button);
      expect(handleClick).toHaveBeenCalledTimes(1);

      await user.type(input, "PROMO50");
      expect(input).toHaveValue("PROMO50");

      await user.selectOptions(select, "offer2");
      expect(select).toHaveValue("offer2");
    });

    it("maintains focus management", async () => {
      const user = userEvent.setup();

      render(
        <PromotionCard>
          <button type="button">First Button</button>
          <input type="text" placeholder="Input field" />
          <button type="button">Second Button</button>
        </PromotionCard>,
      );

      const firstButton = screen.getByRole("button", { name: "First Button" });
      const input = screen.getByPlaceholderText("Input field");
      const secondButton = screen.getByRole("button", {
        name: "Second Button",
      });

      // Test tab navigation
      await user.tab();
      expect(firstButton).toHaveFocus();

      await user.tab();
      expect(input).toHaveFocus();

      await user.tab();
      expect(secondButton).toHaveFocus();
    });

    it("works with Card integration for complex interactions", async () => {
      const user = userEvent.setup();
      const handleSubmit = vi.fn((e) => e.preventDefault());

      render(
        <PromotionCard color="background-contrast">
          <form onSubmit={handleSubmit}>
            <h2>Special Promotion</h2>
            <label htmlFor="email">Email</label>
            <input
              type="email"
              id="email"
              name="email"
              required
              aria-describedby="email-help"
            />
            <p id="email-help">Get exclusive deals in your inbox</p>
            <label htmlFor="subscribe">
              <input type="checkbox" id="subscribe" name="subscribe" />
              Subscribe to newsletter
            </label>
            <button type="submit">Get Offers</button>
          </form>
        </PromotionCard>,
      );

      const emailInput = screen.getByLabelText("Email");
      const checkbox = screen.getByLabelText("Subscribe to newsletter");
      const submitButton = screen.getByRole("button", { name: "Get Offers" });

      // Interact with form elements
      await user.type(emailInput, "test@example.com");
      expect(emailInput).toHaveValue("test@example.com");

      await user.click(checkbox);
      expect(checkbox).toBeChecked();

      await user.click(submitButton);
      expect(handleSubmit).toHaveBeenCalledTimes(1);

      // Verify accessibility is maintained
      expect(emailInput).toHaveAttribute("aria-describedby", "email-help");
      expect(
        screen.getByText("Get exclusive deals in your inbox"),
      ).toBeInTheDocument();
    });
  });
});
