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

// EOLTAS — Baltic parts chain (LT/LV/EE, since 1993). Vue SPA backed by a JSON REST API,
// so we skip the HTML entirely. Two steps, mirroring xparts:
//   1. GET  /lv-lv/rest/search/<code>/2   -> { exactProducts[], analogs[], ... }
//        The trailing "2" is the by-code search mode. The endpoint 404s unless the
//        request carries X-Requested-With: XMLHttpRequest (AJAX-only gate) — verified
//        2026-07-10 (with header -> 200 + results, without -> 404).
//   2. POST /lv-lv/rest/product-price     body {products:[<hash>,...]} -> [{hash,userPrice}]
//        Prices come separately, keyed by each product's opaque `hash`; userPrice is in
//        integer cents (741 -> €7.41).
// exactProducts are matches for the searched number, analogs are cross-references — both
// map to Offers; the UI re-derives exact-vs-analog from the (canonicalized) part number,
// which for these is `brandCode` ("W 712/52" -> "W71252").
// Reachable over plain HTTP/2 (no Cloudflare challenge), unlike rd24/trodo/euautodalas/autodoc.
// Fixture: fixtures/eoltas/W71252.json (search JSON with each product's price merged in).

const BASE = "https://www.eoltas.lv";
const SEARCH = (code: string): string => `${BASE}/lv-lv/rest/search/${encodeURIComponent(code)}/2`;
const PRICE_URL = `${BASE}/lv-lv/rest/product-price`;
const XHR = { "X-Requested-With": "XMLHttpRequest", Accept: "application/json" } as const;

interface EoltasPrice {
  hash: string;
  userPrice: number; // cents
}
interface EoltasProduct {
  hash?: string;
  code?: string;
  brandCode?: string;
  name?: string;
  detailsUrl?: string;
  brand?: { name?: string };
  state?: { name?: string; available?: boolean };
  images?: { thumbnail?: string }[];
  attributes?: { name?: string; value?: string }[];
  /** Injected by fetchRaw from the price call so parse() stays a pure function. */
  _price?: EoltasPrice;
}
interface EoltasSearch {
  exactProducts?: EoltasProduct[];
  analogs?: EoltasProduct[];
}

export const eoltas: StoreAdapter = {
  id: "eoltas",
  displayName: "EOLTAS.lv",
  storeHomepage: "https://www.eoltas.lv",
  enabled: true,
  // GET + 2s politeness gap + POST, each over the network — needs more than the 8s default.
  timeoutMs: 15000,
  fixtureExt: "json",

  async fetchRaw(q: NormalizedQuery, ctx: FetchContext): Promise<string> {
    const searchBody = await ctx.http.get(this.id, SEARCH(q.canonical), { headers: { ...XHR } });
    const data = JSON.parse(searchBody) as EoltasSearch;

    const products = [...(data.exactProducts ?? []), ...(data.analogs ?? [])];
    const hashes = products.map((p) => p.hash).filter((h): h is string => !!h);
    if (hashes.length > 0) {
      const priceBody = await ctx.http.postJson(this.id, PRICE_URL, { products: hashes }, { headers: { ...XHR } });
      const prices = JSON.parse(priceBody) as EoltasPrice[];
      const byHash = new Map(prices.map((p) => [p.hash, p]));
      for (const p of products) {
        const price = p.hash ? byHash.get(p.hash) : undefined;
        if (price) p._price = price;
      }
    }
    return JSON.stringify(data);
  },

  parse(json: string): Offer[] {
    const data = JSON.parse(json) as EoltasSearch;
    const products = [...(data.exactProducts ?? []), ...(data.analogs ?? [])];
    const offers: Offer[] = [];

    for (const p of products) {
      // No price = nothing to compare on; drop it rather than emit an invalid offer.
      const priceEur = p._price ? p._price.userPrice / 100 : NaN;
      if (!validPrice(priceEur)) continue;

      const attributes: OfferAttribute[] = (p.attributes ?? [])
        .filter((a) => a.name || a.value)
        .map((a) => ({ label: (a.name ?? "").trim(), value: (a.value ?? "").trim() }));

      // detailsUrl is already percent-encoded ("W%20712%252F52") — don't re-encode.
      const url = p.detailsUrl ? BASE + p.detailsUrl : "";
      const available = p.state?.available === true;

      offers.push({
        store: eoltas.id,
        brand: p.brand?.name?.trim() || null,
        partNumber: (p.brandCode || p.code || "").trim(),
        title: p.name?.trim() || "",
        priceEur,
        inStock: typeof p.state?.available === "boolean" ? p.state.available : null,
        availability: available ? p.state?.name?.trim() || "Pieejams" : null,
        deliveryNote: null,
        url,
        imageUrl: p.images?.[0]?.thumbnail?.trim() || null,
        attributes,
      });
    }

    return offers;
  },
};
