import { describe, expect, it } from "vitest";
import { ResponseCache } from "../src/core/cache.js";
import { openDatabase } from "../src/core/db.js";
import type { Offer } from "../src/core/types.js";

const offer: Offer = {
  store: "s",
  brand: "MANN-FILTER",
  partNumber: "W 712/52",
  title: "Eļļas filtrs",
  priceEur: 5.42,
  inStock: true,
  availability: "Pieejams",
  deliveryNote: null,
  url: "https://store.example/w71252",
  imageUrl: null,
  attributes: [{ label: "Augstums", value: "92 mm" }],
};

describe("ResponseCache", () => {
  it("round-trips offers within the TTL", () => {
    const cache = new ResponseCache(openDatabase(":memory:"));
    cache.set("s", "W71252", [offer]);
    expect(cache.get("s", "W71252")).toEqual([offer]);
  });

  it("misses for other stores/queries and expires by TTL", async () => {
    const cache = new ResponseCache(openDatabase(":memory:"), { ttlMs: 20 });
    cache.set("s", "W71252", [offer]);
    expect(cache.get("other", "W71252")).toBeNull();
    expect(cache.get("s", "OTHER")).toBeNull();
    await new Promise((r) => setTimeout(r, 30));
    expect(cache.get("s", "W71252")).toBeNull();
  });

  it("caches empty results (a store that found nothing is an answer too)", () => {
    const cache = new ResponseCache(openDatabase(":memory:"));
    cache.set("s", "W71252", []);
    expect(cache.get("s", "W71252")).toEqual([]);
  });

  it("treats rows with a stale offer shape as a miss instead of serving them", () => {
    const cache = new ResponseCache(openDatabase(":memory:"));
    // Simulate a row written before a schema change by corrupting it in place.
    cache.set("s", "W71252", [offer]);
    const { inStock: _dropped, ...legacyOffer } = offer;
    (cache as unknown as { db: import("better-sqlite3").Database }).db
      .prepare("UPDATE response_cache SET offers = ?")
      .run(JSON.stringify([legacyOffer]));
    expect(cache.get("s", "W71252")).toBeNull();
  });

  it("treats unparseable rows as a miss", () => {
    const cache = new ResponseCache(openDatabase(":memory:"));
    cache.set("s", "W71252", [offer]);
    (cache as unknown as { db: import("better-sqlite3").Database }).db
      .prepare("UPDATE response_cache SET offers = 'not json'")
      .run();
    expect(cache.get("s", "W71252")).toBeNull();
  });
});
