import prisma from "@shieldai/db";
import { IdentifierType, WatchListStatus } from "@shieldai/types";
import { createHash, randomUUID } from "crypto";

export class WatchListService {
  async addItem(userId: string, identifierType: IdentifierType, identifierValue: string) {
    const normalized = this.normalize(identifierType, identifierValue);
    const hash = this.computeHash(normalized);

    const existing = await prisma.watchListItem.findFirst({
      where: { userId, identifierHash: hash },
    });

    if (existing) {
      throw new Error(`Identifier already watched: ${normalized}`);
    }

    const tier = await this.getUserTier(userId);
    await this.enforceLimit(userId, tier);

    return prisma.watchListItem.create({
      data: {
        userId,
        identifierType,
        identifierValue: normalized,
        identifierHash: hash,
        status: WatchListStatus.ACTIVE,
      },
    });
  }

  async listItems(userId: string) {
    return prisma.watchListItem.findMany({
      where: { userId },
      orderBy: { createdAt: "desc" },
    });
  }

  async removeItem(userId: string, itemId: string) {
    return prisma.watchListItem.deleteMany({
      where: { id: itemId, userId },
    });
  }

  async getActiveItems(userId: string) {
    return prisma.watchListItem.findMany({
      where: { userId, status: WatchListStatus.ACTIVE },
    });
  }

  async getById(itemId: string) {
    return prisma.watchListItem.findUnique({ where: { id: itemId } });
  }

  normalize(type: IdentifierType, value: string): string {
    const trimmed = value.trim();
    if (type === IdentifierType.EMAIL) {
      return trimmed.toLowerCase();
    }
    if (type === IdentifierType.PHONE) {
      return this.normalizePhone(trimmed);
    }
    return trimmed.replace(/\s/g, "");
  }

  normalizePhone(phone: string): string {
    const digits = phone.replace(/\D/g, "");
    if (digits.length === 10 && digits[0] !== "1") {
      return `+1${digits}`;
    }
    if (digits.length === 11 && digits[0] === "1") {
      return `+${digits}`;
    }
    return `+${digits}`;
  }

  computeHash(value: string): string {
    return createHash("sha256").update(value).digest("hex");
  }

  private async getUserTier(userId: string) {
    const user = await prisma.user.findUnique({ where: { id: userId } });
    return user?.subscriptionTier ?? "BASIC";
  }

  private async enforceLimit(userId: string, tier: string) {
    const count = await prisma.watchListItem.count({ where: { userId } });
    const limits: Record<string, number> = { BASIC: 2, PLUS: 10, PREMIUM: 999 };
    const limit = limits[tier] ?? 2;
    if (count >= limit) {
      throw new Error(`Watch list limit reached (${count}/${limit}) for tier ${tier}`);
    }
  }
}
