import { readFileSync } from "node:fs";
import { describe, expect, it, vi } from "vitest";
import { carparts } from "../src/adapters/carparts.js";
import { normalizeQuery } from "../src/core/normalize.js";
import { OfferSchema, type FetchContext } from "../src/core/types.js";

const json = readFileSync("fixtures/carparts/W71252.json", "utf-8");
const html = readFileSync("fixtures/carparts/34118854273.html", "utf-8");

describe("carparts adapter (fixture: W71252, recorded 2026-07-11)", () => {
  const offers = carparts.parse(json, normalizeQuery("W 712/52")!);

  it("maps the search-API articles to offers", () => {
    expect(offers.length).toBe(1);
  });

  it("every offer passes schema validation", () => {
    for (const o of offers) expect(OfferSchema.safeParse(o).success, JSON.stringify(o)).toBe(true);
  });

  it("parses the MANN match with price, stock and product URL", () => {
    const o = offers[0]!;
    expect(o.brand).toBe("MANN-FILTER");
    expect(o.partNumber).toBe("W 712/52");
    expect(o.title).toBe("Eļļas filtrs");
    expect(o.priceEur).toBe(4.79);
    expect(o.availability).toBe("Pieejams (26 gab.)");
    expect(o.url).toBe("https://carparts.lv/produkts/ellas-filtrs-mann-filter-w-712-52");
    expect(o.imageUrl).toMatch(/^https:\/\/digital-assets\.tecalliance\.services\//);
  });

  it("drops articles without a usable price", () => {
    const offers2 = carparts.parse(
      JSON.stringify([{ articleNumber: "X", mfrName: "Y", genericArticleDescription: "Z", stock: 1 }]),
      normalizeQuery("W 712/52")!,
    );
    expect(offers2.length).toBe(0);
  });

  it("marks out-of-stock articles as unavailable", () => {
    const offers2 = carparts.parse(
      JSON.stringify([{ articleNumber: "W 712/52", mfrName: "MANN", genericArticleDescription: "Filtrs", price: "4.79", stock: 0, slug: "x" }]),
      normalizeQuery("W 712/52")!,
    );
    expect(offers2[0]!.availability).toBeNull();
  });
});

describe("carparts adapter (hosted search fixture: OE 34118854273, recorded 2026-07-16)", () => {
  const offers = carparts.parse(html, normalizeQuery("3411 8 854 273")!);

  it("uses the storefront search route so OE-number alternatives are included", async () => {
    const get = vi.fn().mockResolvedValue(html);
    const ctx = { http: { get } } as unknown as FetchContext;

    await carparts.fetchRaw(normalizeQuery("3411 8 854 273")!, ctx);

    expect(get).toHaveBeenCalledWith(
      "carparts",
      "https://carparts.lv/meklet?s=34118854273",
      { headers: { Accept: "text/html" } },
    );
  });

  it("parses all streamed product cards into valid offers", () => {
    expect(offers).toHaveLength(2);
    for (const offer of offers) expect(() => OfferSchema.parse(offer)).not.toThrow();
  });

  it("extracts price, stock, identity, URL and attributes", () => {
    const offer = offers.find((candidate) => candidate.brand === "BREMBO")!;
    expect(offer).toMatchObject({
      title: "Bremžu diski",
      partNumber: "09.D905.13",
      priceEur: 144.6,
      inStock: true,
      availability: "Pieejams (26 gab.)",
      url: "https://carparts.lv/produkts/bremzu-diski-brembo-09-d905-13",
    });
    expect(offer.attributes).toContainEqual({ label: "Augstums [mm]", value: "66" });
  });

  it("unwraps Next.js image proxy URLs", () => {
    expect(offers.find((offer) => offer.brand === "BREMBO")!.imageUrl).toBe(
      "https://digital-assets.tecalliance.services/images/200/d6c956e5476052f9b7f8fdcb3e03a2fd7529d7d2.jpg",
    );
  });

  it("keeps a card whose heading ends with the brand", () => {
    const offer = offers.find((candidate) => candidate.brand === "ZIMMERMANN")!;
    expect(offer.title).toBe("Bremžu diski");
    expect(offer.partNumber).toBe("34118854273");
  });
});
