import { describe, it, expect } from "vitest";
import { logAccountRotation, runWithRotationItemSink, getRecentRotationEvents } from "../src/main/account-rotation-log";
import type { RotationEvent } from "../src/shared/types";

describe("rotation item-sink (AsyncLocalStorage)", () => {
  it("routes the FULL rotation trail (incl. TEST) to the active item sink", async () => {
    const captured: RotationEvent[] = [];
    await runWithRotationItemSink((ev) => captured.push(ev), async () => {
      logAccountRotation("INFO", "Mega-Debrid Web", "Account 1/3 (ab**xy)", "TEST", { link: "x" });
      logAccountRotation("WARN", "Mega-Debrid Web", "Account 1/3 (ab**xy)", "FAILED", { reason: "Timeout", cooldownSec: 30, next: "Account 2/3 (cd**zw)" });
      logAccountRotation("INFO", "Mega-Debrid Web", "Account 2/3 (cd**zw)", "TEST", { link: "x" });
      logAccountRotation("INFO", "Mega-Debrid Web", "Account 2/3 (cd**zw)", "OK", { fileName: "f.mkv" });
      await Promise.resolve();
    });

    const events = captured.map((e) => e.event);
    expect(events).toEqual(["TEST", "FAILED", "TEST", "OK"]);
    const failed = captured.find((e) => e.event === "FAILED");
    expect(failed?.reason).toBe("Timeout");
    expect(failed?.next).toBe("Account 2/3 (cd**zw)");
  });

  it("does not leak events to the sink outside the run() scope", () => {
    const captured: RotationEvent[] = [];
    logAccountRotation("INFO", "Debrid-Link", "Key 1/2 (k1)", "OK");
    expect(captured).toHaveLength(0);
  });

  it("isolates two parallel item sinks (no cross-attribution)", async () => {
    const a: RotationEvent[] = [];
    const b: RotationEvent[] = [];
    await Promise.all([
      runWithRotationItemSink((ev) => a.push(ev), async () => {
        logAccountRotation("INFO", "Mega-Debrid Web", "Account 1 (a)", "TEST");
        await new Promise((r) => setTimeout(r, 10));
        logAccountRotation("INFO", "Mega-Debrid Web", "Account 1 (a)", "OK");
      }),
      runWithRotationItemSink((ev) => b.push(ev), async () => {
        logAccountRotation("INFO", "Debrid-Link", "Key 1 (b)", "TEST");
        await new Promise((r) => setTimeout(r, 5));
        logAccountRotation("WARN", "Debrid-Link", "Key 1 (b)", "FAILED", { reason: "badToken" });
      })
    ]);
    expect(a.every((e) => e.provider === "Mega-Debrid Web")).toBe(true);
    expect(b.every((e) => e.provider === "Debrid-Link")).toBe(true);
    expect(a.map((e) => e.event)).toEqual(["TEST", "OK"]);
    expect(b.map((e) => e.event)).toEqual(["TEST", "FAILED"]);
  });

  it("still feeds the global UI ring (outcomes only, TEST filtered)", () => {
    logAccountRotation("INFO", "Mega-Debrid API", "Account 9 (zz)", "TEST");
    logAccountRotation("INFO", "Mega-Debrid API", "Account 9 (zz)", "OK", { fileName: "ring.mkv" });
    const ring = getRecentRotationEvents(10);
    expect(ring.some((e) => e.event === "OK" && e.accountLabel === "Account 9 (zz)")).toBe(true);
    expect(ring.some((e) => e.event === "TEST" && e.accountLabel === "Account 9 (zz)")).toBe(false);
  });
});
