import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";

import { AdapterRegistry } from "../packages/connectors/pacifica/src/adapterRegistry";
import type { PositionSnapshot } from "../packages/domain/src/types";

type PositionMap = Record<string, PositionSnapshot>;

function createMockAdapter(map: PositionMap) {
  let currentAccountId: string | undefined;
  return {
    setAccountId: vi.fn((id: string) => {
      currentAccountId = id;
    }),
    getPosition: vi.fn(async (symbol: string) => {
      const snapshot = map[symbol];
      if (snapshot) {
        return { ...snapshot, accountId: currentAccountId };
      }
      return {
        symbol,
        base: 0,
        quote: 0,
        ts: Date.now(),
        accountId: currentAccountId
      };
    })
  } as any;
}

describe("AdapterRegistry", () => {
  const now = 1_700_000_000_000;

  beforeEach(() => {
    vi.useFakeTimers();
    vi.setSystemTime(now);
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  it("attaches adapters and resolves them by id and role", () => {
    const registry = new AdapterRegistry();
    const makerAdapter = createMockAdapter({});
    const hedgerAdapter = createMockAdapter({});

    registry.attach("maker", makerAdapter, "maker");
    registry.attach("hedger", hedgerAdapter, "hedger");

    expect(registry.get("maker")).toBe(makerAdapter);

    const hedgerEntry = registry.findEntryByRole("hedger");
    expect(hedgerEntry).toBeDefined();
    expect(hedgerEntry?.id).toBe("hedger");
    expect(hedgerEntry?.adapter).toBe(hedgerAdapter);
    expect(makerAdapter.setAccountId).toHaveBeenCalledWith("maker");
    expect(hedgerAdapter.setAccountId).toHaveBeenCalledWith("hedger");
  });

  it("collects positions with account attribution", async () => {
    const registry = new AdapterRegistry();

    const makerAdapter = createMockAdapter({
      BTC: { symbol: "BTC", base: 0.25, quote: 12_500, ts: now }
    });
    const hedgerAdapter = createMockAdapter({
      BTC: { symbol: "BTC", base: -0.2, quote: -10_000, ts: now }
    });

    registry.attach("maker", makerAdapter, "maker");
    registry.attach("hedger", hedgerAdapter, "hedger");

    const snapshots = await registry.collectPositions("BTC");

    expect(snapshots).toEqual([
      { symbol: "BTC", base: 0.25, quote: 12_500, ts: now, accountId: "maker" },
      { symbol: "BTC", base: -0.2, quote: -10_000, ts: now, accountId: "hedger" }
    ]);

    expect(makerAdapter.getPosition).toHaveBeenCalledWith("BTC");
    expect(hedgerAdapter.getPosition).toHaveBeenCalledWith("BTC");
  });
});
