import { render, screen, fireEvent, act } from "@testing-library/react";
import { SearchBar } from "@/components/header/SearchBar";
import { searchProducts } from "@/lib/product-actions";
import { vi, describe, it, expect, beforeEach } from "vitest";
import React from "react";

// Mock next/navigation
vi.mock("next/navigation", () => ({
  useRouter: () => ({
    push: vi.fn(),
  }),
}));

// Mock searchProducts server action in its correct location
vi.mock("@/lib/product-actions", () => ({
  searchProducts: vi.fn(),
}));

describe("SearchBar Performance (Optimized)", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.useFakeTimers();
  });

  it("should call searchProducts when typing more than 2 characters", async () => {
    vi.mocked(searchProducts).mockResolvedValue({
        success: true,
        data: { total: 1, documents: [{ id: "1", title: "Test Product", price: 10, image: "" } as any] },
        code: 200
    });
    render(<SearchBar />);
    const input = screen.getByPlaceholderText("Online-Shop durchsuchen...");

    await act(async () => {
      fireEvent.change(input, { target: { value: "test" } });
    });

    // Fast-forward debounce time
    await act(async () => {
      vi.advanceTimersByTime(320);
    });

    expect(searchProducts).toHaveBeenCalledTimes(1);
  });

  it("should ONLY call searchProducts once for same query (cache hit)", async () => {
    vi.mocked(searchProducts).mockResolvedValue({
        success: true,
        data: { total: 1, documents: [{ id: "1", title: "Test Product", price: 10, image: "" } as any] },
        code: 200
    });
    render(<SearchBar />);
    const input = screen.getByPlaceholderText("Online-Shop durchsuchen...");

    // First search
    await act(async () => {
      fireEvent.change(input, { target: { value: "apple" } });
    });
    await act(async () => {
      vi.advanceTimersByTime(320);
    });
    expect(searchProducts).toHaveBeenCalledTimes(1);

    // Clear search
    await act(async () => {
      fireEvent.change(input, { target: { value: "" } });
    });

    // Second search with same query
    await act(async () => {
      fireEvent.change(input, { target: { value: "apple" } });
    });
    await act(async () => {
      vi.advanceTimersByTime(320);
    });

    // POST-OPTIMIZATION: should still be 1 because of cache!
    expect(searchProducts).toHaveBeenCalledTimes(1);
  });

  it("should respect trimming when checking cache", async () => {
    vi.mocked(searchProducts).mockResolvedValue({
        success: true,
        data: { total: 1, documents: [{ id: "1", title: "Test Product", price: 10, image: "" } as any] },
        code: 200
    });
    render(<SearchBar />);
    const input = screen.getByPlaceholderText("Online-Shop durchsuchen...");

    // Search with spaces
    await act(async () => {
      fireEvent.change(input, { target: { value: "  banana  " } });
    });
    await act(async () => {
      vi.advanceTimersByTime(320);
    });
    expect(searchProducts).toHaveBeenCalledWith({
        page: 1,
        pageSize: 10,
        query: "banana",
        requestType: "search",
        sortOrder: "ASC"
    });
    expect(searchProducts).toHaveBeenCalledTimes(1);

    // Search without spaces
    await act(async () => {
      fireEvent.change(input, { target: { value: "banana" } });
    });
    await act(async () => {
      vi.advanceTimersByTime(320);
    });

    // Should hit cache for "banana"
    expect(searchProducts).toHaveBeenCalledTimes(1);
  });
});
