import { DataSource, Severity } from "@shieldai/types";

export interface HIBPBreach {
  name: string;
  title: string;
  domain: string;
  loginCount: number;
  passwordCount: number;
  date: Date;
  breachDate: Date;
  addedDate: Date;
  pwnCount: number;
  dataClasses: string[];
  logo: string;
}

export class HIBPService {
  private baseUrl = "https://haveibeenpwned.com/api/v3";
  private apiKey?: string;

  constructor(apiKey?: string) {
    this.apiKey = apiKey;
  }

  async checkEmail(email: string): Promise<HIBPBreach[]> {
    const url = `${this.baseUrl}/breached-account/${encodeURIComponent(email)}`;
    const headers: Record<string, string> = {
      "User-Agent": "ShieldAI-DarkWatch/1.0",
      "HIBP-API-Version": "3",
    };
    if (this.apiKey) {
      headers["hibp-api-key"] = this.apiKey;
    }

    const response = await fetch(url, { headers });

    if (response.status === 404) {
      return [];
    }

    if (response.status === 410) {
      throw new Error(`Email not found in HIBP: ${email}`);
    }

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10);
      throw new Error(`HIBP rate limited. Retry after ${retryAfter}s`);
    }

    if (!response.ok) {
      throw new Error(`HIBP API error: ${response.status} ${response.statusText}`);
    }

    return response.json() as Promise<HIBPBreach[]>;
  }

  async rangeQuery(hashPrefix: string): Promise<string[]> {
    const url = `${this.baseUrl}/range/${hashPrefix}`;
    const response = await fetch(url, {
      headers: { "User-Agent": "ShieldAI-DarkWatch/1.0" },
    });

    if (!response.ok) {
      throw new Error(`HIBP range API error: ${response.status}`);
    }

    const text = await response.text();
    return text.split("\n").map((line) => line.split(":")[0].toUpperCase());
  }

  getSeverity(breach: HIBPBreach): Severity {
    const criticalClasses = ["Password", "Email Address", "Bank Account", "Credit Card", "Social Security Number"];
    const warningClasses = ["Phone Number", "IP Address", "Geolocation", "IP & User agent"];

    const hasCritical = breach.dataClasses.some((c) => criticalClasses.includes(c));
    const hasWarning = breach.dataClasses.some((c) => warningClasses.includes(c));

    const breachAge = (Date.now() - breach.breachDate.getTime()) / (1000 * 60 * 60 * 24);

    if (hasCritical) return Severity.CRITICAL;
    if (hasWarning) return Severity.WARNING;
    if (breachAge > 365) return Severity.INFO;

    return Severity.WARNING;
  }

  mapToDataSource(): DataSource {
    return DataSource.HIBP;
  }
}
