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

// IC24.lv — Inter Cars' Latvian B2C storefront (the working sibling of motointegrator.lv,
// which is currently down). NOT Cloudflare-walled: the catalog and part-number search are
// open. The catch is the PRICE — Inter Cars renders prices into the search HTML only for a
// warm anonymous session (the token its homepage/`/auth.php` establishes). A cold direct GET
// returns the same page with EMPTY price boxes. So we fetch through the resident browser
// (BrowserHub.fetchOriginHtml warms the homepage first, then same-origin-fetches the search
// URL) — same mechanism as trodo, minus any challenge. It rides onDemand purely for the warm
// session; with no CF wall it never asks for a solve.
//
// Search URL: `/detalas/search=<base64(CANONICAL)>` (e.g. W71252 → "VzcxMjUy"). Results are
// the searched part plus cross-brand analogues (like handler/trodo).
//
// PRICE PARITY: Inter Cars shows a net (ex-VAT, B2B-style) price too, but every other store
// here compares on the VAT-inclusive consumer price. We therefore read `.price_gross_2`
// (gross, VAT-incl — 6.76) NOT `.price_net_2` (hidden net — 5.59), so ic24 isn't made to
// look falsely cheapest. Fixture: fixtures/ic24/W71252.html (2026-07-13).

const HOME = "https://www.ic24.lv";

/** Canonical part numbers are ASCII; keep this portable across Node and WebView runtimes. */
export function encodeIc24Search(canonical: string): string {
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  let encoded = "";
  for (let index = 0; index < canonical.length; index += 3) {
    const first = canonical.charCodeAt(index);
    const hasSecond = index + 1 < canonical.length;
    const hasThird = index + 2 < canonical.length;
    const second = hasSecond ? canonical.charCodeAt(index + 1) : 0;
    const third = hasThird ? canonical.charCodeAt(index + 2) : 0;
    const bits = (first << 16) | (second << 8) | third;
    encoded += alphabet[(bits >> 18) & 63];
    encoded += alphabet[(bits >> 12) & 63];
    encoded += hasSecond ? alphabet[(bits >> 6) & 63] : "=";
    encoded += hasThird ? alphabet[bits & 63] : "=";
  }
  return encoded;
}

const SEARCH_URL = (canonical: string): string =>
  `${HOME}/detalas/search=${encodeIc24Search(canonical)}`;

const SELECTORS = {
  card: "[data-product-impresion]", // one offer per element; id="wynik_N"
  brand: 'input[id^="manufacture_"]', // value="MANN-FILTER"
  partNumber: 'input[id^="index_"]', // value="W 712/52"
  title: 'input[id^="description_"]', // value="Eļļas filtrs MANN-FILTER W 712/52"
  link: 'a[href^="/produkti/"]',
  image: 'img[src*="webcdn.intercars"], img[src*="/thumbnails/"]',
  priceGross: ".price_gross_2", // VAT-inclusive selling price (see PRICE PARITY note)
  stock: 'span[datatest-id="tap-item-product-stock"]', // in-stock unit count, e.g. "9"
};

export const ic24: StoreAdapter = {
  id: "ic24",
  displayName: "IC24.lv",
  storeHomepage: HOME,
  enabled: true,
  fetchMode: "onDemand", // routes through the resident browser for its warm session (no CF)
  timeoutMs: 45000, // homepage warm-up + same-origin search fetch of a ~390KB page

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

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

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

      const partNumber = (card.find(SELECTORS.partNumber).attr("value") ?? "").trim();
      const href = card.find(SELECTORS.link).attr("href") ?? "";
      const priceEur = parsePriceEur(card.find(SELECTORS.priceGross).first().text());
      if (!partNumber || !href || !validPrice(priceEur)) return;

      const brand = (card.find(SELECTORS.brand).attr("value") ?? "").trim() || null;
      const title = (card.find(SELECTORS.title).attr("value") ?? "").trim() || partNumber;
      const imageUrl = card.find(SELECTORS.image).first().attr("src") ?? null;

      const qty = parseInt(card.find(SELECTORS.stock).first().text().trim(), 10);
      const inStock = Number.isFinite(qty) && qty > 0;
      const availability = inStock ? `Pieejams (${qty} gab.)` : "Nav pieejams";

      offers.push({
        store: ic24.id,
        brand,
        partNumber,
        title,
        priceEur,
        inStock,
        availability,
        deliveryNote: null,
        url: new URL(href, HOME).toString(),
        imageUrl,
        attributes: [],
      });
    });

    return offers;
  },
};
