import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { WatchListService } from "../src/watchlist/WatchListService";
import prisma from "@shieldai/db";
import { IdentifierType } from "@shieldai/types";

let runId = Date.now();

describe("WatchListService", () => {
  let service: WatchListService;
  let userId: string;

  beforeEach(async () => {
    runId = Date.now();
    service = new WatchListService();
    const user = await prisma.user.create({
      data: {
        email: `test-${runId}@shieldai.local`,
        name: "Test User",
        subscriptionTier: "PREMIUM",
      },
    });
    userId = user.id;
  });

  afterEach(async () => {
    await prisma.watchListItem.deleteMany({ where: { userId } });
    await prisma.user.delete({ where: { id: userId } });
  });

  it("adds an email identifier", async () => {
    const item = await service.addItem(userId, IdentifierType.EMAIL, `test-${runId}@example.com`);
    expect(item.identifierValue).toBe(`test-${runId}@example.com`);
    expect(item.identifierType).toBe(IdentifierType.EMAIL);
    expect(item.identifierHash).toHaveLength(64);
  });

  it("adds a phone identifier", async () => {
    const digits = String(runId).padStart(10, "0").slice(-10);
    const phone = `${digits.slice(0,3)}-${digits.slice(3,7)}-${digits.slice(7)}`;
    const item = await service.addItem(userId, IdentifierType.PHONE, phone);
    expect(item.identifierType).toBe(IdentifierType.PHONE);
    expect(item.identifierValue).toMatch(/^\+1\d{10}$/);
  });

  it("deduplicates by hash", async () => {
    await service.addItem(userId, IdentifierType.EMAIL, `dedup-${runId}@example.com`);
    const duplicate = service.addItem(userId, IdentifierType.EMAIL, `DEDUP-${runId}@EXAMPLE.COM`);
    await expect(duplicate).rejects.toThrow("Identifier already watched");
  });

  it("lists items", async () => {
    await service.addItem(userId, IdentifierType.EMAIL, `list-a-${runId}@example.com`);
    await service.addItem(userId, IdentifierType.EMAIL, `list-b-${runId}@example.com`);
    const items = await service.listItems(userId);
    expect(items).toHaveLength(2);
  });

  it("removes an item", async () => {
    const item = await service.addItem(userId, IdentifierType.EMAIL, `remove-${runId}@example.com`);
    const result = await service.removeItem(userId, item.id);
    expect(result.count).toBe(1);
    const remaining = await service.listItems(userId);
    expect(remaining).toHaveLength(0);
  });

  it("enforces BASIC tier limit", async () => {
    const basicUser = await prisma.user.update({
      where: { id: userId },
      data: { subscriptionTier: "BASIC" },
    });
    await service.addItem(basicUser.id, IdentifierType.EMAIL, `basic-1-${runId}@example.com`);
    await service.addItem(basicUser.id, IdentifierType.EMAIL, `basic-2-${runId}@example.com`);
    const third = service.addItem(basicUser.id, IdentifierType.EMAIL, `basic-3-${runId}@example.com`);
    await expect(third).rejects.toThrow("Watch list limit reached");
  });
});
