import * as cheerio from "cheerio";
import { parsePriceEur } from "../core/normalize.js";
import { inStockFromText } from "./util.js";
import type { FetchContext, NormalizedQuery, Offer, OfferAttribute, StoreAdapter } from "../core/types.js";

// robots.txt checked 2026-07-10: /spare-parts and /meklet not disallowed (only internal paths are).
// Fixture: fixtures/partsale/W71252.html (recorded 2026-07-10).
// Note: promo offers show the old price struck through; the real price is `.onlyprice`
// inside `.priceline` — never take the first €-looking number in the card.

const BASE = "https://partsale.lv";
const SEARCH_URL = (q: string) => `${BASE}/spare-parts/meklet?q=${encodeURIComponent(q)}`;

const SELECTORS = {
  card: "#galleryRec .card",
  titleLink: "h3.litit a",
  brandImg: "img.manufacturerm",
  partNumberLabel: "small", // the <small>Rezerves daļas numurs:</small><b>…</b> pair
  partNumberLabelText: "Rezerves daļas numurs",
  availability: 'strong[title="Pieejamība"]',
  price: ".priceline .onlyprice",
  image: ".result-image img", // lazy: real URL in data-src (src holds the same value in the fixture)
  attrItem: "ul.product-parameters li", // label is the li's own text, value sits in the <span>
};

// img.partsale.lv pre-generates /images/{100,200,400,800}/<hash>.jpg; every other size
// answers 200 with an EMPTY body (verified by GET size, 2026-07-10 — HEAD status lies).
// Listings link the 200px thumb; we bump it to 800 so the hover zoom isn't a blur.
function upsizeImage(url: string): string {
  return url.replace("/images/200/", "/images/800/");
}

export const partsale: StoreAdapter = {
  id: "partsale",
  displayName: "Partsale.lv",
  storeHomepage: "https://partsale.lv",
  enabled: true,
  timeoutMs: 8000,

  async fetchRaw(q: NormalizedQuery, ctx: FetchContext): Promise<string> {
    return ctx.http.get(this.id, SEARCH_URL(q.canonical));
  },

  parse(html: string): Offer[] {
    const $ = cheerio.load(html);
    const offers: Offer[] = [];

    $(SELECTORS.card).each((_, el) => {
      const card = $(el);

      const link = card.find(SELECTORS.titleLink).first();
      const href = link.attr("href") ?? "";
      const url = href.startsWith("http") ? href : href ? BASE + href : "";

      const partNumber = card
        .find(SELECTORS.partNumberLabel)
        .filter((_, s) => $(s).text().includes(SELECTORS.partNumberLabelText))
        .first()
        .next("b")
        .text()
        .trim();

      const attributes: OfferAttribute[] = [];
      card.find(SELECTORS.attrItem).each((_, li) => {
        const value = $(li).find("span").first().text().replace(/\u00a0/g, " ").trim();
        const label = $(li).clone().children("span").remove().end().text().trim();
        if (label || value) attributes.push({ label, value });
      });

      const imgEl = card.find(SELECTORS.image).first();
      const imgSrc = imgEl.attr("data-src") ?? imgEl.attr("src");

      const availability = card.find(SELECTORS.availability).first().text().trim() || null;

      offers.push({
        store: partsale.id,
        brand: card.find(SELECTORS.brandImg).attr("alt")?.trim() || null,
        partNumber,
        title: link.text().trim(),
        priceEur: parsePriceEur(card.find(SELECTORS.price).first().text()),
        inStock: inStockFromText(availability),
        availability,
        deliveryNote: null,
        url,
        imageUrl: imgSrc ? upsizeImage(imgSrc) : null,
        attributes,
      });
    });

    return offers;
  },
};
