import prisma from "@shieldai/db";
import { ExposureResult, DataSource, Severity } from "@shieldai/types";
import { createHash } from "crypto";

export class MatchingEngine {
  async matchExposure(
    watchListItemId: string,
    dataSource: DataSource,
    breachName: string,
    exposedAt: Date,
    dataType: string[],
    severity: Severity,
    details?: string
  ): Promise<ExposureResult | null> {
    const contentHash = this.computeContentHash(dataSource, breachName, watchListItemId);

    const existing = await prisma.exposure.findUnique({
      where: { contentHash },
    });

    if (existing) {
      return null;
    }

    const exposure = await prisma.exposure.create({
      data: {
        watchListItemId,
        dataSource,
        breachName,
        exposedAt,
        dataType,
        severity,
        details,
        contentHash,
      },
    });

    return {
      dataSource: exposure.dataSource,
      breachName: exposure.breachName,
      exposedAt: exposure.exposedAt,
      dataType: exposure.dataType,
      severity: exposure.severity,
      details: exposure.details || "",
    };
  }

  async getExposuresForUser(userId: string): Promise<ExposureResult[]> {
    const items = await prisma.watchListItem.findMany({
      where: { userId },
      include: { exposures: true },
    });

    const results: ExposureResult[] = [];
    for (const item of items) {
      for (const exp of item.exposures) {
        results.push({
          dataSource: exp.dataSource,
          breachName: exp.breachName,
          exposedAt: exp.exposedAt,
          dataType: exp.dataType,
          severity: exp.severity,
          details: exp.details || "",
        });
      }
    }

    return results.sort((a, b) => {
      const severityOrder = { CRITICAL: 0, WARNING: 1, INFO: 2 };
      return severityOrder[a.severity] - severityOrder[b.severity];
    });
  }

  async getExposureById(exposureId: string): Promise<ExposureResult | null> {
    const exposure = await prisma.exposure.findUnique({
      where: { id: exposureId },
      include: { watchListItem: true },
    });

    if (!exposure) return null;

    return {
      dataSource: exposure.dataSource,
      breachName: exposure.breachName,
      exposedAt: exposure.exposedAt,
      dataType: exposure.dataType,
      severity: exposure.severity,
      details: exposure.details || "",
    };
  }

  countExposures(userId: string): Promise<number> {
    return prisma.exposure.count({
      where: {
        watchListItem: { userId },
      },
    });
  }

  computeContentHash(dataSource: DataSource, breachName: string, watchListItemId: string): string {
    const raw = `${dataSource}:${breachName}:${watchListItemId}`;
    return createHash("sha256").update(raw).digest("hex");
  }
}
