import type { FetchContext, NormalizedQuery, Offer, StoreAdapter } from "../core/types.js";
import { validPrice } from "./util.js";

// Handler.lv — Nuxt storefront over the handlerparts TecDoc backend. The homepage
// challenges headless browsers, but the search API itself is a plain JSON endpoint
// reachable over HTTP/2 with no auth, no CAPTCHA and no Origin check (verified
// 2026-07-11): GET api.handlerparts.com/api/Parts/Search?articleNumber=<code>&...
// Required params: articleNumber, siteCode ("h"+TLD -> "hlv"), sessionId (any client
// UUID), language/languageCode, countryCode. The response is a marketplace: `data.offers`
// lists MANY supplier offers for the searched part AND its cross-brand analogues (180 for
// W71252). We collapse to the cheapest offer per (brand, manufacturer code) so Handler
// contributes one comparable price per part like the other stores.
// Fixture: fixtures/handler/W71252.json (the raw Parts/Search envelope).

const API = "https://api.handlerparts.com/api/Parts/Search";
const SITE = "https://handler.lv";
const SITE_CODE = "hlv"; // "h" + handler.lv TLD, per the site's own siteCode()
// A stable anonymous session id — the API issues nothing, the client just mints a UUID;
// keeping it constant lets PoliteHttp's per-URL cache work and looks like one visitor.
const SESSION_ID = "08e634ce-3447-41f6-b3bd-89aa2f5d4abb";

const SEARCH = (code: string): string =>
  `${API}?siteCode=${SITE_CODE}&sessionId=${SESSION_ID}` +
  `&language=lv&languageCode=lv&countryCode=lv&articleNumber=${encodeURIComponent(code)}`;

interface HandlerProduct {
  article?: string;
  articleId?: string;
  manufacturerCode?: string;
  name?: string;
  brandName?: string;
}
interface HandlerOffer {
  product?: HandlerProduct;
  price?: number;
  availability?: number;
  availabilityNotAccurate?: boolean;
  deliveryTimeInDays?: number;
}
interface HandlerResponse {
  data?: { offers?: HandlerOffer[] };
}

export const handler: StoreAdapter = {
  id: "handler",
  displayName: "Handler.lv",
  storeHomepage: "https://handler.lv",
  enabled: true,
  timeoutMs: 12000,
  directRefreshTimeoutMs: 45000,
  fixtureExt: "json",

  async fetchRaw(q: NormalizedQuery, ctx: FetchContext): Promise<string> {
    return ctx.http.get(this.id, SEARCH(q.canonical), {
      headers: { Accept: "application/json", Referer: `${SITE}/lv` },
    });
  },

  parse(json: string): Offer[] {
    const offers = (JSON.parse(json) as HandlerResponse).data?.offers;
    if (!Array.isArray(offers)) return [];

    // Collapse the marketplace to the cheapest live offer per distinct part.
    const best = new Map<string, { offer: HandlerOffer; priceEur: number }>();
    for (const o of offers) {
      const priceEur = typeof o.price === "number" ? o.price : NaN;
      if (!validPrice(priceEur)) continue;
      const p = o.product ?? {};
      const key = `${p.brandName ?? ""}|${p.manufacturerCode ?? p.article ?? ""}`;
      const current = best.get(key);
      if (!current || handlerOfferIsBetter(o, priceEur, current.offer, current.priceEur)) {
        best.set(key, { offer: o, priceEur });
      }
    }

    const result: Offer[] = [];
    for (const { offer: o, priceEur } of best.values()) {
      const p = o.product ?? {};
      const inStock = typeof o.availability === "number" && o.availability > 0;
      const availability = inStock
        ? o.availabilityNotAccurate
          ? "Pieejams"
          : `Pieejams (${o.availability} gab.)`
        : null;

      result.push({
        store: handler.id,
        brand: p.brandName?.trim() || null,
        partNumber: (p.manufacturerCode || p.article || "").trim(),
        title: p.name?.trim() || "",
        priceEur,
        inStock: typeof o.availability === "number" ? inStock : null,
        availability,
        deliveryNote: o.deliveryTimeInDays ? `Piegāde ~${o.deliveryTimeInDays} d.` : null,
        url: p.articleId ? `${SITE}/lv/Product/${p.articleId}` : `${SITE}/lv/detail-search?articleNumber=${encodeURIComponent(p.article ?? "")}`,
        imageUrl:
          p.brandName && p.article
            ? `${API.replace("/Parts/Search", "")}/Images/GetImageByProduct/${encodeURIComponent(p.brandName)}/${encodeURIComponent(p.article)}/0/true`
            : null,
        attributes: [],
        sourceRef: p.articleId?.trim() || null,
      });
    }

    return result;
  },
};

function handlerOfferIsBetter(candidate: HandlerOffer, price: number, current: HandlerOffer, currentPrice: number): boolean {
  if (price !== currentPrice) return price < currentPrice;
  return (candidate.availability ?? -1) > (current.availability ?? -1);
}
