import { act, renderHook } from "@testing-library/react";
import type { ReactNode } from "react";
import { MemoryRouter } from "react-router-dom";
import { describe, expect, it } from "vitest";
import { DEFAULT_SORT } from "./constants";
import { useOrchestratorFilters } from "./useOrchestratorFilters";

const createWrapper = (initialEntry: string) => {
  const Wrapper = ({ children }: { children: ReactNode }) => (
    <MemoryRouter initialEntries={[initialEntry]}>{children}</MemoryRouter>
  );
  Wrapper.displayName = "RouterWrapper";
  return Wrapper;
};

describe("useOrchestratorFilters", () => {
  it("parses a valid sort query param", () => {
    const { result } = renderHook(() => useOrchestratorFilters(), {
      wrapper: createWrapper("/ready?sort=title-asc"),
    });

    expect(result.current.sort).toEqual({
      key: "title",
      direction: "asc",
    });
  });

  it("falls back to default sort for invalid sort query params", () => {
    const cases = [
      "/ready?sort=title",
      "/ready?sort=invalid-asc",
      "/ready?sort=title-sideways",
    ];

    for (const entry of cases) {
      const { result } = renderHook(() => useOrchestratorFilters(), {
        wrapper: createWrapper(entry),
      });
      expect(result.current.sort).toEqual(DEFAULT_SORT);
    }
  });

  it("parses multiple sources and countries from the query string", () => {
    const { result } = renderHook(() => useOrchestratorFilters(), {
      wrapper: createWrapper(
        "/ready?source=indeed&source=linkedin&countries=united%20kingdom",
      ),
    });

    expect(result.current.sourcesFilter).toEqual(["indeed", "linkedin"]);
    expect(result.current.countriesFilter).toEqual(["united kingdom"]);
  });

  it("writes multiple sources and countries to the query string", () => {
    const { result } = renderHook(() => useOrchestratorFilters(), {
      wrapper: createWrapper("/ready"),
    });

    act(() => {
      result.current.setSourceSelection(["indeed", "linkedin"], []);
    });
    act(() => {
      result.current.setCountrySelection(["united kingdom", "canada"], []);
    });

    const params = result.current.searchParams;
    expect(params.getAll("source").sort()).toEqual(["indeed", "linkedin"]);
    expect(params.get("countries")).toBe("canada,united kingdom");
  });

  it("parses and writes country and source excludes", () => {
    const { result } = renderHook(() => useOrchestratorFilters(), {
      wrapper: createWrapper(
        "/ready?sourceExclude=linkedin&countriesExclude=united%20kingdom",
      ),
    });
    expect(result.current.sourcesExcludeFilter).toEqual(["linkedin"]);
    expect(result.current.countriesExcludeFilter).toEqual(["united kingdom"]);

    act(() => {
      result.current.setSourceSelection(["indeed"], ["linkedin"]);
    });
    act(() => {
      result.current.setCountrySelection(["canada"], ["united kingdom"]);
    });
    const params = result.current.searchParams;
    expect(params.getAll("source")).toEqual(["indeed"]);
    expect(params.getAll("sourceExclude")).toEqual(["linkedin"]);
    expect(params.get("countries")).toBe("canada");
    expect(params.get("countriesExclude")).toBe("united kingdom");
  });

  it("parses found date, employer tokens, skip list toggle, and reset clears them", () => {
    const { result } = renderHook(() => useOrchestratorFilters(), {
      wrapper: createWrapper(
        "/ready?foundAfter=2026-04-01&foundBefore=2026-04-30&employer=acme&employerExclude=temp&skipList=0",
      ),
    });

    expect(result.current.foundAfterYmd).toBe("2026-04-01");
    expect(result.current.foundBeforeYmd).toBe("2026-04-30");
    expect(result.current.employerIncludeFilter).toEqual(["acme"]);
    expect(result.current.employerExcludeFilter).toEqual(["temp"]);
    expect(result.current.applySettingsCompanySkipList).toBe(false);

    act(() => {
      result.current.resetFilters();
    });
    const params = result.current.searchParams;
    expect(params.get("foundAfter")).toBeNull();
    expect(params.get("employer")).toBeNull();
    expect(params.get("skipList")).toBeNull();
  });
});
