import { render, screen } from "@testing-library/react";

// Mock breakpoints since SCSS modules don't work in tests
vi.mock("../../../styles/export/breakpoint", () => ({
  default: {
    xs: "0px",
    sm: "480px",
    md: "768px",
    lg: "992px",
    xl: "1240px",
    xxl: "1380px",
    xxxl: "1920px",
  },
  xs: "0px",
  sm: "480px",
  md: "768px",
  lg: "992px",
  xl: "1240px",
  xxl: "1380px",
  xxxl: "1920px",
}));

import { Image } from "../Image";

/**
 * Unit testy pre Image komponentu
 *
 * Testy pokrývajú:
 *
 * **Základné renderovanie:**
 * • Renderovanie s predvolenou CSS triedou 'img'
 * • Pridávanie dodatočných CSS tried cez className prop
 * • Správne nastavenie alt atribútu
 * • Správne nastavenie src atribútu pre string src
 * • Predávanie dodatočných props do img elementu
 *
 * **String src (jednoduché obrázky):**
 * • Renderovanie ako img element keď je src string
 * • Žiadne source elementy pre string src
 *
 * **Object src (responzívne obrázky):**
 * • Renderovanie ako picture element keď je src objekt
 * • Nastavenie default src pre img element
 * • Správny počet source elementov (bez default)
 * • Vylúčenie default z source elementov
 * • Správne srcSet atribúty pre source elementy
 * • Správne media atribúty pre source elementy
 * • Sortovanie breakpointov v zostupnom poradí
 *
 * **Všetky breakpointy:**
 * • Správne spracovanie všetkých možných breakpointov (xxxl, xxl, xl, lg, md, sm, xs)
 * • Sortovanie všetkých breakpointov v správnom zostupnom poradí
 * • Správne media queries pre všetky breakpointy
 *
 * **Edge cases:**
 * • Objekt s len default vlastnosťou
 * • Objekt bez default vlastnosti
 * • Prázdny objekt
 * • Objekt s vlastnými breakpoint kľúčmi
 *
 * **Accessibility:**
 * • Vždy má alt atribút
 * • Prázdny alt pre dekoratívne obrázky
 * • Zachovanie alt atribútu v picture elemente
 *
 * **Component metadata:**
 * • Správny displayName
 */

const singleSource = "/__image_snapshots__/picture-element-md-snap.png";
const multipleSources = {
  default: "/__image_snapshots__/picture-element-md-snap.png",
  xl: "/__image_snapshots__/picture-element-xl-snap.png",
  lg: "/__image_snapshots__/picture-element-lg-snap.png",
};

const allBreakpoints = {
  default: "/__image_snapshots__/default.png",
  xxxl: "/__image_snapshots__/xxxl.png",
  xxl: "/__image_snapshots__/xxl.png",
  xl: "/__image_snapshots__/xl.png",
  lg: "/__image_snapshots__/lg.png",
  md: "/__image_snapshots__/md.png",
  sm: "/__image_snapshots__/sm.png",
  xs: "/__image_snapshots__/xs.png",
};

describe("Image Component", () => {
  describe("Basic rendering", () => {
    it("renders with default class when no className provided", () => {
      const { getByTestId } = render(
        <Image data-testid="test-id" alt="test" src={singleSource} />,
      );
      expect(getByTestId("test-id")).toHaveClass("img");
    });

    it("renders with additional class when className is provided", () => {
      const { getByTestId } = render(
        <Image
          data-testid="test-id"
          className="test-class"
          alt="test"
          src={singleSource}
        />,
      );
      expect(getByTestId("test-id")).toHaveClass("img", "test-class");
    });

    it("renders with correct alt attribute", () => {
      render(<Image alt="Test alt text" src={singleSource} />);
      expect(screen.getByAltText("Test alt text")).toBeInTheDocument();
    });

    it("renders with correct src attribute for string src", () => {
      const { container } = render(<Image alt="test" src={singleSource} />);
      expect(new URL(container.querySelector("img").src).pathname).toEqual(
        singleSource,
      );
    });

    it("passes through additional props to img element", () => {
      const { container } = render(
        <Image
          alt="test"
          src={singleSource}
          data-custom="custom-value"
          id="test-id"
        />,
      );
      const img = container.querySelector("img");
      expect(img.getAttribute("data-custom")).toBe("custom-value");
      expect(img.getAttribute("id")).toBe("test-id");
    });
  });

  describe("String src (simple image)", () => {
    it("renders as img element when src is string", () => {
      const { container } = render(<Image alt="test" src={singleSource} />);
      expect(container.querySelector("img")).toBeTruthy();
      expect(container.querySelector("picture")).toBeFalsy();
    });

    it("does not render source elements when src is string", () => {
      const { container } = render(<Image alt="test" src={singleSource} />);
      expect(container.querySelectorAll("source")).toHaveLength(0);
    });
  });

  describe("Object src (responsive image)", () => {
    it("renders as picture element when src is object", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      expect(container.querySelector("picture")).toBeTruthy();
    });

    it("renders img with default src when src is object", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      const img = container.querySelector("img");
      expect(img.getAttribute("src")).toEqual(multipleSources.default);
    });

    it("renders correct number of source elements", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      // Should have 2 source elements (xl and lg, excluding default)
      expect(container.querySelectorAll("source")).toHaveLength(2);
    });

    it("excludes default from source elements", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      const sources = container.querySelectorAll("source");
      sources.forEach((source) => {
        expect(source.getAttribute("srcSet")).not.toBe(multipleSources.default);
      });
    });

    it("renders source elements with correct srcSet attributes", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      const sources = container.querySelectorAll("source");

      const srcSetValues = Array.from(sources).map((s) =>
        s.getAttribute("srcSet"),
      );
      expect(srcSetValues).toContain(multipleSources.xl);
      expect(srcSetValues).toContain(multipleSources.lg);
    });

    it("renders source elements with correct media attributes", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      const sources = container.querySelectorAll("source");

      const mediaValues = Array.from(sources).map((s) =>
        s.getAttribute("media"),
      );
      expect(mediaValues).toContain("(min-width: 1240px)"); // xl
      expect(mediaValues).toContain("(min-width: 992px)"); // lg
    });

    it("sorts breakpoints in descending order", () => {
      const { container } = render(<Image alt="test" src={multipleSources} />);
      const sources = container.querySelectorAll("source");

      // First source should be xl (larger breakpoint)
      expect(sources[0].getAttribute("media")).toBe("(min-width: 1240px)");
      // Second source should be lg (smaller breakpoint)
      expect(sources[1].getAttribute("media")).toBe("(min-width: 992px)");
    });
  });

  describe("All breakpoints support", () => {
    it("handles all possible breakpoints correctly", () => {
      const { container } = render(<Image alt="test" src={allBreakpoints} />);
      const sources = container.querySelectorAll("source");

      // Should have 7 source elements (all except default)
      expect(sources).toHaveLength(7);
    });

    it("sorts all breakpoints in correct descending order", () => {
      const { container } = render(<Image alt="test" src={allBreakpoints} />);
      const sources = container.querySelectorAll("source");

      const expectedOrder = ["xxxl", "xxl", "xl", "lg", "md", "sm", "xs"];
      const actualOrder = Array.from(sources).map((s) => {
        const srcSet = s.getAttribute("srcSet");
        return Object.keys(allBreakpoints).find(
          (key) => allBreakpoints[key] === srcSet,
        );
      });

      expect(actualOrder).toEqual(expectedOrder);
    });

    it("renders correct media queries for all breakpoints", () => {
      const { container } = render(<Image alt="test" src={allBreakpoints} />);
      const sources = container.querySelectorAll("source");

      const expectedMediaQueries = [
        "(min-width: 1920px)", // xxxl (custom)
        "(min-width: 1380px)", // xxl (from SCSS)
        "(min-width: 1240px)", // xl
        "(min-width: 992px)", // lg
        "(min-width: 768px)", // md
        "(min-width: 480px)", // sm
        "(min-width: 0px)", // xs
      ];

      const actualMediaQueries = Array.from(sources).map((s) =>
        s.getAttribute("media"),
      );
      expect(actualMediaQueries).toEqual(expectedMediaQueries);
    });
  });

  describe("Edge cases", () => {
    it("handles object with only default property", () => {
      const srcOnlyDefault = { default: singleSource };
      const { container } = render(<Image alt="test" src={srcOnlyDefault} />);

      expect(container.querySelector("picture")).toBeTruthy();
      expect(container.querySelectorAll("source")).toHaveLength(0);
      expect(container.querySelector("img").getAttribute("src")).toBe(
        singleSource,
      );
    });

    it("handles object with missing default property gracefully", () => {
      const srcWithoutDefault = { xl: "/test-xl.png", lg: "/test-lg.png" };
      const { container } = render(
        <Image alt="test" src={srcWithoutDefault} />,
      );

      expect(container.querySelector("picture")).toBeTruthy();
      expect(container.querySelectorAll("source")).toHaveLength(2);
      // Should still render img but with undefined src
      expect(container.querySelector("img")).toBeTruthy();
    });

    it("handles empty object gracefully", () => {
      const emptySrc = {};
      const { container } = render(<Image alt="test" src={emptySrc} />);

      expect(container.querySelector("picture")).toBeTruthy();
      expect(container.querySelectorAll("source")).toHaveLength(0);
      expect(container.querySelector("img")).toBeTruthy();
    });

    it("handles object with custom breakpoint keys", () => {
      const customSrc = {
        default: "/default.png",
        custom: "/custom.png",
        another: "/another.png",
      };
      const { container } = render(<Image alt="test" src={customSrc} />);

      expect(container.querySelector("picture")).toBeTruthy();
      expect(container.querySelectorAll("source")).toHaveLength(2);
    });
  });

  describe("Accessibility", () => {
    it("always has alt attribute", () => {
      render(<Image alt="Accessible image" src={singleSource} />);
      expect(screen.getByAltText("Accessible image")).toBeInTheDocument();
    });

    it("works with empty alt for decorative images", () => {
      render(<Image alt="" src={singleSource} />);
      expect(screen.getByAltText("")).toBeInTheDocument();
    });

    it("maintains alt attribute in picture element", () => {
      const { container } = render(
        <Image alt="Responsive image" src={multipleSources} />,
      );
      const img = container.querySelector("img");
      expect(img.getAttribute("alt")).toBe("Responsive image");
    });
  });

  describe("Component metadata", () => {
    it("has correct displayName", () => {
      expect(Image.displayName).toBe("Image");
    });
  });
});
