import { describe, it, expect } from "vitest";
import { parseItemSearchParams, buildItemSearchUrl } from "./item-search-params";

const sp = (qs: string) => new URLSearchParams(qs);

describe("parseItemSearchParams", () => {
  it("returns defaults for empty input", () => {
    const p = parseItemSearchParams(sp(""));
    expect(p).toEqual({
      q: null,
      categorySlug: null,
      brand: [],
      size: [],
      condition: [],
      colors: [],
      storeId: [],
      minPrice: null,
      maxPrice: null,
      sort: "newest",
      page: 1,
      perPage: 24,
    });
  });

  it("defaults sort to relevance when q is present", () => {
    const p = parseItemSearchParams(sp("q=leather"));
    expect(p.sort).toBe("relevance");
  });

  it("respects explicit sort", () => {
    const p = parseItemSearchParams(sp("q=leather&sort=price_asc"));
    expect(p.sort).toBe("price_asc");
  });

  it("clamps per_page to max 60", () => {
    const p = parseItemSearchParams(sp("per_page=200"));
    expect(p.perPage).toBe(60);
  });

  it("clamps page to minimum 1", () => {
    const p = parseItemSearchParams(sp("page=0"));
    expect(p.page).toBe(1);
  });

  it("parses array params", () => {
    const p = parseItemSearchParams(sp("brand=Nike&brand=Adidas&condition=EUC"));
    expect(p.brand).toEqual(["Nike", "Adidas"]);
    expect(p.condition).toEqual(["EUC"]);
  });

  it("falls back to default for invalid sort", () => {
    const p = parseItemSearchParams(sp("sort=banana"));
    expect(p.sort).toBe("newest");
  });
});

describe("buildItemSearchUrl", () => {
  it("omits defaults", () => {
    const current = parseItemSearchParams(sp(""));
    const url = buildItemSearchUrl(current, {});
    expect(url).toBe("/items");
  });

  it("merges a patch into current state", () => {
    const current = parseItemSearchParams(sp("brand=Nike"));
    const url = buildItemSearchUrl(current, { brand: ["Nike", "Adidas"] });
    expect(url).toContain("brand=Nike");
    expect(url).toContain("brand=Adidas");
  });

  it("replaces arrays when patched", () => {
    const current = parseItemSearchParams(sp("brand=Nike&brand=Adidas"));
    const url = buildItemSearchUrl(current, { brand: ["Puma"] });
    expect(url).toContain("brand=Puma");
    expect(url).not.toContain("brand=Nike");
  });

  it("resets page on non-page patch", () => {
    const current = parseItemSearchParams(sp("page=5&brand=Nike"));
    const url = buildItemSearchUrl(current, { brand: ["Adidas"] });
    expect(url).not.toContain("page=");
  });

  it("preserves explicit page when page is in the patch", () => {
    const current = parseItemSearchParams(sp("brand=Nike"));
    const url = buildItemSearchUrl(current, { page: 3 });
    expect(url).toContain("page=3");
  });
});
