import { describe, it, expect, vi } from "vitest";
import { render, screen, fireEvent } from "@testing-library/svelte";
import SearchBar from "./SearchBar.svelte";

describe("SearchBar", () => {
  describe("Rendering Tests", () => {
    it("should render input field with placeholder", () => {
      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search test...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByPlaceholderText("Search test...");
      expect(input).toBeTruthy();
    });

    it("should render search icon", () => {
      const { container } = render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const svg = container.querySelector("svg");
      expect(svg).toBeTruthy();
      const classString = svg?.getAttribute("class") || "";
      expect(classString).toContain("w-5");
      expect(classString).toContain("h-5");
    });

    it("should display current value in input", () => {
      render(SearchBar, {
        props: {
          value: "test query",
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByDisplayValue("test query") as HTMLInputElement;
      expect(input.value).toBe("test query");
    });

    it("should apply custom className", () => {
      const { container } = render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput: vi.fn(),
          className: "custom-class",
        },
      });

      const wrapper = container.firstChild as HTMLElement;
      expect(wrapper.className).toContain("custom-class");
    });

    it("should have proper accessibility attributes", () => {
      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search genres...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByPlaceholderText("Search genres...") as HTMLInputElement;
      expect(input.type).toBe("text");
    });
  });

  describe("Interaction Tests", () => {
    it("should call onInput callback when user types", () => {
      const onInput = vi.fn();

      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput,
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      fireEvent.input(input, { target: { value: "test" } });

      expect(onInput).toHaveBeenCalled();
    });

    it("should pass correct value to onInput callback", () => {
      const onInput = vi.fn();

      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput,
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      fireEvent.input(input, { target: { value: "album search" } });

      // Check that callback was called with the typed value
      expect(onInput).toHaveBeenCalledWith("album search");
    });

    it("should handle multiple input changes", () => {
      const onInput = vi.fn();

      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput,
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      fireEvent.input(input, { target: { value: "test" } });
      fireEvent.input(input, { target: { value: "testing" } });

      expect(onInput).toHaveBeenCalled();
    });
  });

  describe("Edge Cases", () => {
    it("should handle empty search query", () => {
      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      expect(input.value).toBe("");
    });

    it("should handle special characters in value", () => {
      render(SearchBar, {
        props: {
          value: '@$%^&*()',
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByDisplayValue("@$%^&*()") as HTMLInputElement;
      expect(input.value).toBe("@$%^&*()");
    });

    it("should handle very long input values", () => {
      const longValue = "a".repeat(500);
      render(SearchBar, {
        props: {
          value: longValue,
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByDisplayValue(longValue) as HTMLInputElement;
      expect(input.value).toBe(longValue);
    });

    it("should work with numeric input", () => {
      const onInput = vi.fn();

      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput,
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      fireEvent.input(input, { target: { value: "12345" } });

      expect(onInput).toHaveBeenCalledWith("12345");
    });
  });

  describe("Requirement Tests", () => {
    it("should support searching with spaces", () => {
      const onInput = vi.fn();

      render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput,
        },
      });

      const input = screen.getByPlaceholderText("Search...") as HTMLInputElement;
      fireEvent.input(input, { target: { value: "search multiple words" } });

      expect(onInput).toHaveBeenCalledWith("search multiple words");
    });

    it("should work as controlled component with value prop", () => {
      render(SearchBar, {
        props: {
          value: "initial value",
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = screen.getByDisplayValue("initial value") as HTMLInputElement;
      expect(input.value).toBe("initial value");
    });

    it("should have proper styling for dark theme", () => {
      const { container } = render(SearchBar, {
        props: {
          value: "",
          placeholder: "Search...",
          onInput: vi.fn(),
        },
      });

      const input = container.querySelector("input");
      expect(input).toBeTruthy();
      const classString = input?.getAttribute("class") || "";
      expect(classString.length).toBeGreaterThan(0);
      expect(classString).toContain("bg-");
      expect(classString).toContain("text-white");
      expect(classString).toContain("placeholder-gray");
    });
  });
});
