/**
 * Callout Component Tests
 *
 * Tests for blog callout/alert component
 *
 * Test Coverage:
 * - Different types (info, success, warning, tip)
 * - Styling for each type
 * - Icon rendering
 * - Title rendering (optional)
 * - Children content rendering
 * - Default type behavior
 * - Color schemes and backgrounds
 * - Dark mode support
 */

import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Callout from "@/components/blog/Callout";

describe("Callout Component", () => {
  describe("Basic Rendering", () => {
    it("should render children content", () => {
      render(
        <Callout>
          <p>This is a callout message</p>
        </Callout>,
      );

      expect(screen.getByText("This is a callout message")).toBeInTheDocument();
    });

    it("should render with default info type", () => {
      const { container } = render(<Callout>Test content</Callout>);

      expect(container.querySelector(".border-blue-500")).toBeInTheDocument();
      expect(container.querySelector(".bg-blue-50")).toBeInTheDocument();
    });

    it("should render without title", () => {
      render(<Callout>Content only</Callout>);

      expect(screen.getByText("Content only")).toBeInTheDocument();
      expect(screen.queryByRole("heading")).not.toBeInTheDocument();
    });

    it("should render with title", () => {
      render(<Callout title="Important Notice">This is important</Callout>);

      expect(screen.getByText("Important Notice")).toBeInTheDocument();
      expect(screen.getByText("This is important")).toBeInTheDocument();
    });

    it("should render title as h4 heading", () => {
      render(<Callout title="Test Title">Content</Callout>);

      const title = screen.getByText("Test Title");
      expect(title.tagName).toBe("H4");
    });
  });

  describe("Info Type", () => {
    it("should render info callout with correct background", () => {
      const { container } = render(<Callout type="info">Info message</Callout>);

      expect(container.querySelector(".bg-blue-50")).toBeInTheDocument();
      expect(
        container.querySelector(".dark\\:bg-blue-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should render info callout with correct border", () => {
      const { container } = render(<Callout type="info">Info message</Callout>);

      expect(container.querySelector(".border-blue-500")).toBeInTheDocument();
    });

    it("should render info callout with correct icon", () => {
      render(<Callout type="info">Info message</Callout>);

      expect(screen.getByText("💡")).toBeInTheDocument();
    });

    it("should render info callout with correct icon background", () => {
      const { container } = render(<Callout type="info">Info message</Callout>);

      expect(container.querySelector(".bg-blue-500")).toBeInTheDocument();
    });

    it("should render info callout with all styling classes", () => {
      const { container } = render(<Callout type="info">Info message</Callout>);

      const callout = container.firstChild;
      expect(callout).toHaveClass(
        "border-l-4",
        "rounded-r-xl",
        "p-6",
        "my-8",
        "shadow-md",
      );
    });
  });

  describe("Success Type", () => {
    it("should render success callout with correct background", () => {
      const { container } = render(
        <Callout type="success">Success message</Callout>,
      );

      expect(container.querySelector(".bg-green-50")).toBeInTheDocument();
      expect(
        container.querySelector(".dark\\:bg-green-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should render success callout with correct border", () => {
      const { container } = render(
        <Callout type="success">Success message</Callout>,
      );

      expect(container.querySelector(".border-green-500")).toBeInTheDocument();
    });

    it("should render success callout with correct icon", () => {
      render(<Callout type="success">Success message</Callout>);

      expect(screen.getByText("✅")).toBeInTheDocument();
    });

    it("should render success callout with correct icon background", () => {
      const { container } = render(
        <Callout type="success">Success message</Callout>,
      );

      expect(container.querySelector(".bg-green-500")).toBeInTheDocument();
    });

    it("should render success callout with title", () => {
      render(
        <Callout type="success" title="Operation Successful">
          The action completed successfully
        </Callout>,
      );

      expect(screen.getByText("Operation Successful")).toBeInTheDocument();
      expect(
        screen.getByText("The action completed successfully"),
      ).toBeInTheDocument();
    });
  });

  describe("Warning Type", () => {
    it("should render warning callout with correct background", () => {
      const { container } = render(
        <Callout type="warning">Warning message</Callout>,
      );

      expect(container.querySelector(".bg-orange-50")).toBeInTheDocument();
      expect(
        container.querySelector(".dark\\:bg-orange-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should render warning callout with correct border", () => {
      const { container } = render(
        <Callout type="warning">Warning message</Callout>,
      );

      expect(container.querySelector(".border-orange-500")).toBeInTheDocument();
    });

    it("should render warning callout with correct icon", () => {
      render(<Callout type="warning">Warning message</Callout>);

      expect(screen.getByText("⚠️")).toBeInTheDocument();
    });

    it("should render warning callout with correct icon background", () => {
      const { container } = render(
        <Callout type="warning">Warning message</Callout>,
      );

      expect(container.querySelector(".bg-orange-500")).toBeInTheDocument();
    });

    it("should render warning callout with title", () => {
      render(
        <Callout type="warning" title="Caution Required">
          Please be careful with this operation
        </Callout>,
      );

      expect(screen.getByText("Caution Required")).toBeInTheDocument();
      expect(
        screen.getByText("Please be careful with this operation"),
      ).toBeInTheDocument();
    });
  });

  describe("Tip Type", () => {
    it("should render tip callout with correct background", () => {
      const { container } = render(<Callout type="tip">Tip message</Callout>);

      expect(container.querySelector(".bg-purple-50")).toBeInTheDocument();
      expect(
        container.querySelector(".dark\\:bg-purple-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should render tip callout with correct border", () => {
      const { container } = render(<Callout type="tip">Tip message</Callout>);

      expect(container.querySelector(".border-purple-500")).toBeInTheDocument();
    });

    it("should render tip callout with correct icon", () => {
      render(<Callout type="tip">Tip message</Callout>);

      expect(screen.getByText("💡")).toBeInTheDocument();
    });

    it("should render tip callout with correct icon background", () => {
      const { container } = render(<Callout type="tip">Tip message</Callout>);

      expect(container.querySelector(".bg-purple-500")).toBeInTheDocument();
    });

    it("should render tip callout with title", () => {
      render(
        <Callout type="tip" title="Pro Tip">
          Here is a helpful tip for you
        </Callout>,
      );

      expect(screen.getByText("Pro Tip")).toBeInTheDocument();
      expect(
        screen.getByText("Here is a helpful tip for you"),
      ).toBeInTheDocument();
    });
  });

  describe("Content Rendering", () => {
    it("should render simple text content", () => {
      render(<Callout>Simple text</Callout>);

      expect(screen.getByText("Simple text")).toBeInTheDocument();
    });

    it("should render HTML content", () => {
      render(
        <Callout>
          <p>Paragraph 1</p>
          <p>Paragraph 2</p>
        </Callout>,
      );

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

    it("should render complex nested content", () => {
      render(
        <Callout>
          <div>
            <strong>Bold text</strong>
            <em>Italic text</em>
            <ul>
              <li>Item 1</li>
              <li>Item 2</li>
            </ul>
          </div>
        </Callout>,
      );

      expect(screen.getByText("Bold text")).toBeInTheDocument();
      expect(screen.getByText("Italic text")).toBeInTheDocument();
      expect(screen.getByText("Item 1")).toBeInTheDocument();
      expect(screen.getByText("Item 2")).toBeInTheDocument();
    });

    it("should render code blocks", () => {
      render(
        <Callout>
          <code>const x = 10;</code>
        </Callout>,
      );

      expect(screen.getByText("const x = 10;")).toBeInTheDocument();
    });

    it("should render links", () => {
      render(
        <Callout>
          Check out <a href="/docs">our docs</a>
        </Callout>,
      );

      const link = screen.getByText("our docs");
      expect(link.tagName).toBe("A");
      expect(link).toHaveAttribute("href", "/docs");
    });
  });

  describe("Layout and Structure", () => {
    it("should have flex layout", () => {
      const { container } = render(<Callout>Content</Callout>);

      expect(
        container.querySelector(".flex.items-start.gap-4"),
      ).toBeInTheDocument();
    });

    it("should render icon container with correct size", () => {
      const { container } = render(<Callout>Content</Callout>);

      const iconContainer = container.querySelector(".w-10.h-10");
      expect(iconContainer).toBeInTheDocument();
      expect(iconContainer).toHaveClass(
        "rounded-lg",
        "flex",
        "items-center",
        "justify-center",
      );
    });

    it("should render icon as flex-shrink-0", () => {
      const { container } = render(<Callout>Content</Callout>);

      expect(container.querySelector(".flex-shrink-0")).toBeInTheDocument();
    });

    it("should render content in flex-grow container", () => {
      const { container } = render(<Callout>Content</Callout>);

      expect(container.querySelector(".flex-grow")).toBeInTheDocument();
    });

    it("should have left border styling", () => {
      const { container } = render(<Callout>Content</Callout>);

      const callout = container.firstChild;
      expect(callout).toHaveClass("border-l-4");
    });

    it("should have rounded corners", () => {
      const { container } = render(<Callout>Content</Callout>);

      const callout = container.firstChild;
      expect(callout).toHaveClass("rounded-r-xl");
    });

    it("should have padding and margins", () => {
      const { container } = render(<Callout>Content</Callout>);

      const callout = container.firstChild;
      expect(callout).toHaveClass("p-6", "my-8");
    });

    it("should have shadow", () => {
      const { container } = render(<Callout>Content</Callout>);

      const callout = container.firstChild;
      expect(callout).toHaveClass("shadow-md");
    });
  });

  describe("Title Styling", () => {
    it("should style title with correct classes", () => {
      render(<Callout title="Test Title">Content</Callout>);

      const title = screen.getByText("Test Title");
      expect(title).toHaveClass(
        "font-bold",
        "text-gray-900",
        "dark:text-white",
        "text-lg",
        "mb-2",
      );
    });

    it("should have spacing below title", () => {
      render(<Callout title="Test Title">Content</Callout>);

      const title = screen.getByText("Test Title");
      expect(title).toHaveClass("mb-2");
    });

    it("should render title in all callout types", () => {
      const types = ["info", "success", "warning", "tip"] as const;

      types.forEach((type) => {
        const { container } = render(
          <Callout type={type} title={`${type} Title`}>
            Content
          </Callout>,
        );

        expect(screen.getByText(`${type} Title`)).toBeInTheDocument();
        container.remove();
      });
    });
  });

  describe("Content Styling", () => {
    it("should style content text", () => {
      const { container } = render(<Callout>Content text</Callout>);

      const content = container.querySelector(
        ".text-gray-700.dark\\:text-gray-300.leading-relaxed",
      );
      expect(content).toBeInTheDocument();
    });

    it("should have relaxed line height", () => {
      const { container } = render(<Callout>Content</Callout>);

      expect(container.querySelector(".leading-relaxed")).toBeInTheDocument();
    });
  });

  describe("Icon Styling", () => {
    it("should render icon in white text", () => {
      const { container } = render(<Callout>Content</Callout>);

      const icon = container.querySelector(".text-white.text-lg");
      expect(icon).toBeInTheDocument();
    });

    it("should render icon with shadow", () => {
      const { container } = render(<Callout>Content</Callout>);

      const iconContainer = container.querySelector(".shadow-lg");
      expect(iconContainer).toBeInTheDocument();
    });

    it("should render different icons for different types", () => {
      const { container: infoContainer } = render(
        <Callout type="info">Info</Callout>,
      );
      expect(infoContainer.textContent).toContain("💡");

      const { container: successContainer } = render(
        <Callout type="success">Success</Callout>,
      );
      expect(successContainer.textContent).toContain("✅");

      const { container: warningContainer } = render(
        <Callout type="warning">Warning</Callout>,
      );
      expect(warningContainer.textContent).toContain("⚠️");

      const { container: tipContainer } = render(
        <Callout type="tip">Tip</Callout>,
      );
      expect(tipContainer.textContent).toContain("💡");
    });
  });

  describe("Dark Mode Support", () => {
    it("should have dark mode background for info", () => {
      const { container } = render(<Callout type="info">Content</Callout>);

      expect(
        container.querySelector(".dark\\:bg-blue-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should have dark mode background for success", () => {
      const { container } = render(<Callout type="success">Content</Callout>);

      expect(
        container.querySelector(".dark\\:bg-green-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should have dark mode background for warning", () => {
      const { container } = render(<Callout type="warning">Content</Callout>);

      expect(
        container.querySelector(".dark\\:bg-orange-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should have dark mode background for tip", () => {
      const { container } = render(<Callout type="tip">Content</Callout>);

      expect(
        container.querySelector(".dark\\:bg-purple-950\\/30"),
      ).toBeInTheDocument();
    });

    it("should have dark mode text colors", () => {
      const { container } = render(<Callout title="Title">Content</Callout>);

      expect(container.querySelector(".dark\\:text-white")).toBeInTheDocument();
      expect(
        container.querySelector(".dark\\:text-gray-300"),
      ).toBeInTheDocument();
    });
  });

  describe("Accessibility", () => {
    it("should use semantic heading for title", () => {
      render(<Callout title="Important">Content</Callout>);

      const title = screen.getByText("Important");
      expect(title.tagName).toBe("H4");
    });

    it("should have proper color contrast", () => {
      const { container } = render(<Callout type="info">Content</Callout>);

      // Blue-500 border on blue-50 background provides good contrast
      expect(container.querySelector(".border-blue-500")).toBeInTheDocument();
      expect(container.querySelector(".bg-blue-50")).toBeInTheDocument();
    });

    it("should use div for semantic structure", () => {
      const { container } = render(<Callout>Content</Callout>);

      expect(container.firstChild?.nodeName).toBe("DIV");
    });

    it("should be keyboard navigable when containing links", () => {
      render(
        <Callout>
          <a href="/test">Test Link</a>
        </Callout>,
      );

      const link = screen.getByText("Test Link");
      expect(link).toBeInTheDocument();
      expect(link.tagName).toBe("A");
    });
  });

  describe("Edge Cases", () => {
    it("should handle empty children", () => {
      const { container } = render(<Callout>{""}</Callout>);

      expect(container.firstChild).toBeInTheDocument();
    });

    it("should handle very long content", () => {
      const longText = "A".repeat(1000);
      render(<Callout>{longText}</Callout>);

      expect(screen.getByText(longText)).toBeInTheDocument();
    });

    it("should handle special characters in content", () => {
      render(<Callout>Special chars: &lt; &gt; &amp; © ™ € £</Callout>);

      expect(screen.getByText(/Special chars/)).toBeInTheDocument();
    });

    it("should handle special characters in title", () => {
      render(<Callout title="Title with <special> &chars">Content</Callout>);

      expect(screen.getByText(/Title with/)).toBeInTheDocument();
    });

    it("should handle React fragments as children", () => {
      render(
        <Callout>
          <>
            <p>First</p>
            <p>Second</p>
          </>
        </Callout>,
      );

      expect(screen.getByText("First")).toBeInTheDocument();
      expect(screen.getByText("Second")).toBeInTheDocument();
    });
  });

  describe("Type Variations Comparison", () => {
    it("should render all four types differently", () => {
      const { container: infoContainer } = render(
        <Callout type="info">Info</Callout>,
      );

      const { container: successContainer } = render(
        <Callout type="success">Success</Callout>,
      );

      const { container: warningContainer } = render(
        <Callout type="warning">Warning</Callout>,
      );

      const { container: tipContainer } = render(
        <Callout type="tip">Tip</Callout>,
      );

      // Each should have different border colors
      expect(
        infoContainer.querySelector(".border-blue-500"),
      ).toBeInTheDocument();
      expect(
        successContainer.querySelector(".border-green-500"),
      ).toBeInTheDocument();
      expect(
        warningContainer.querySelector(".border-orange-500"),
      ).toBeInTheDocument();
      expect(
        tipContainer.querySelector(".border-purple-500"),
      ).toBeInTheDocument();
    });

    it("should use info as default when type is not specified", () => {
      const { container: defaultContainer } = render(
        <Callout>Default</Callout>,
      );

      const { container: infoContainer } = render(
        <Callout type="info">Info</Callout>,
      );

      // Should have same border color
      expect(
        defaultContainer.querySelector(".border-blue-500"),
      ).toBeInTheDocument();
      expect(
        infoContainer.querySelector(".border-blue-500"),
      ).toBeInTheDocument();
    });
  });

  describe("Performance", () => {
    it("should render quickly", () => {
      const startTime = performance.now();
      render(
        <Callout type="info" title="Test">
          Content
        </Callout>,
      );
      const renderTime = performance.now() - startTime;

      expect(renderTime).toBeLessThan(100);
    });

    it("should handle multiple callouts efficiently", () => {
      const startTime = performance.now();

      for (let i = 0; i < 10; i++) {
        const { container } = render(
          <Callout type="info">Callout {i}</Callout>,
        );
        container.remove();
      }

      const totalTime = performance.now() - startTime;
      expect(totalTime).toBeLessThan(500);
    });
  });
});
