import { readFile } from "node:fs/promises";
import { describe, expect, it } from "vitest";
import { createEngine, EngineRequestError } from "../src/engine.js";
import { MemoryResponseCache } from "../src/core/memoryCache.js";
import type { BrowserFetcher, PoliteFetcher } from "../src/core/types.js";

const unusedBrowser: BrowserFetcher = {
  fetchJson: async () => { throw new Error("browser fetch not expected"); },
  fetchOriginHtml: async () => { throw new Error("browser fetch not expected"); },
  fetchPageHtml: async () => { throw new Error("browser fetch not expected"); },
};

describe("portable engine", () => {
  it("executes a Partsale fixture search and returns the REST wire shape", async () => {
    const fixture = await readFile("fixtures/partsale/W71252.html", "utf8");
    const http: PoliteFetcher = {
      get: async () => fixture,
      postForm: async () => { throw new Error("POST not expected"); },
      postJson: async () => { throw new Error("POST not expected"); },
    };
    const engine = createEngine({ http, browser: unusedBrowser, cache: new MemoryResponseCache() });

    expect(engine.stores().stores).toContainEqual(expect.objectContaining({ id: "partsale" }));
    const response = await engine.search("partsale", "W 712/52");
    expect(response).toMatchObject({
      store: "partsale",
      displayName: "Partsale.lv",
      query: "W71252",
      ok: true,
      cached: false,
      httpStatus: 200,
    });
    expect(response.offers.length).toBeGreaterThan(0);
    expect((await engine.search("partsale", "W71252")).cached).toBe(true);
  });

  it("rejects invalid engine requests before performing I/O", async () => {
    const http = {} as PoliteFetcher;
    const engine = createEngine({ http, browser: unusedBrowser, cache: new MemoryResponseCache() });
    await expect(engine.search("missing", "W71252")).rejects.toMatchObject({
      code: "unknown_store",
      statusCode: 404,
    } satisfies Partial<EngineRequestError>);
    await expect(engine.search("partsale", "x")).rejects.toMatchObject({
      code: "invalid_query",
      statusCode: 400,
    } satisfies Partial<EngineRequestError>);
  });

  it("keeps outbound links as real anchors for native new-tab and copy-link behavior", async () => {
    const resultsTemplate = await readFile("web/src/app/features/search-results/search-results.html", "utf8");
    const planTemplate = await readFile("web/src/app/features/purchase-plan/purchase-plan.html", "utf8");
    expect(resultsTemplate).toContain('<a hlmBtn variant="outline" size="sm" [href]="outUrl(offer)" target="_blank" rel="noopener"');
    expect(planTemplate).toContain('[href]="planOutUrl(line.candidate.offer)"');
    expect(resultsTemplate).not.toContain('(click)="openOffer(offer)"');
  });
});
