import { createHash } from "node:crypto";
import { existsSync, readFileSync } from "node:fs";

import { validateReleaseCandidateRecord } from "./release-candidate.mjs";

export const RESEND_DAILY_LIMIT = 80;
export const RESEND_MONTHLY_LIMIT = 2_400;
export const DELIVERY_CATEGORIES = Object.freeze(["qq", "163", "enterprise"]);
export const DELIVERY_SAMPLE_SIZE = 20;
export const DELIVERY_MINIMUM_WITHIN_TWO_MINUTES = 19;
export const DELIVERY_WINDOW_SECONDS = 120;
export const EXPECTED_WP7_01_COMMIT = "623cad25b2a2a9a003502c9a92ebd318dad06248";

const emailPattern = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i;
const absolutePathPattern = /(?:[A-Z]:[\\/]|\\\\|\/Users\/|\/home\/)/i;
const sensitiveKeyPattern = /"(?:api[_ -]?key|secret|password|authorization|bearer|cookie|session[_ -]?token|verification[_ -]?code|private[_ -]?content|prompt|image)"\s*:/i;

function object(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
}

function errorList(...values) {
  return [...new Set(values.flat().filter((value) => typeof value === "string" && value.length > 0))];
}

export function validateDomainCheck(value) {
  const item = object(value);
  const freeRules = object(item?.free_rules);
  const spf = object(item?.spf);
  const dkim = object(item?.dkim);
  const errors = [];
  if (item?.schema_version !== "1.0") errors.push("schema_version");
  if (item?.service !== "resend") errors.push("service");
  if (item?.source !== "human_controlled_real") errors.push("source");
  if (item?.status !== "verified") errors.push("status");
  if (item?.domain_controlled !== true) errors.push("domain_controlled");
  if (spf?.status !== "pass") errors.push("spf");
  if (dkim?.status !== "pass") errors.push("dkim");
  if (freeRules?.status !== "verified") errors.push("free_rules.status");
  if (freeRules?.daily_limit !== RESEND_DAILY_LIMIT) errors.push("free_rules.daily_limit");
  if (freeRules?.monthly_limit !== RESEND_MONTHLY_LIMIT) errors.push("free_rules.monthly_limit");
  if (freeRules?.paid_fallback_enabled !== false) errors.push("free_rules.paid_fallback_enabled");
  return errorList(errors);
}

export function validateDeliverySummary(value) {
  const item = object(value);
  const errors = [];
  if (item?.schema_version !== "1.0") errors.push("schema_version");
  if (item?.service !== "resend") errors.push("service");
  if (item?.source !== "human_controlled_real") errors.push("source");
  if (item?.status !== "verified") errors.push("status");
  if (!Array.isArray(item?.categories) || item.categories.length !== DELIVERY_CATEGORIES.length) {
    errors.push("categories");
  } else {
    const categories = item.categories.map((entry) => entry?.category).sort();
    if (categories.join("|") !== DELIVERY_CATEGORIES.slice().sort().join("|")) errors.push("categories.names");
    for (const entry of item.categories) {
      if (!Number.isInteger(entry?.sent_count) || entry.sent_count !== DELIVERY_SAMPLE_SIZE) errors.push(`${entry?.category ?? "unknown"}.sent_count`);
      if (!Number.isInteger(entry?.delivered_within_120_seconds)
        || entry.delivered_within_120_seconds < DELIVERY_MINIMUM_WITHIN_TWO_MINUTES
        || entry.delivered_within_120_seconds > DELIVERY_SAMPLE_SIZE) {
        errors.push(`${entry?.category ?? "unknown"}.delivered_within_120_seconds`);
      }
      if (!Number.isFinite(entry?.max_latency_seconds) || entry.max_latency_seconds > DELIVERY_WINDOW_SECONDS) errors.push(`${entry?.category ?? "unknown"}.max_latency_seconds`);
      if (entry?.mock_used !== false) errors.push(`${entry?.category ?? "unknown"}.mock_used`);
      if (entry?.preseeded_account_used !== false) errors.push(`${entry?.category ?? "unknown"}.preseeded_account_used`);
    }
  }
  return errorList(errors);
}

export function validateAuthResult(value) {
  const item = object(value);
  const ordinary = object(item?.ordinary);
  const admin = object(item?.admin);
  const errors = [];
  if (item?.schema_version !== "1.0") errors.push("schema_version");
  if (item?.service !== "resend") errors.push("service");
  if (item?.source !== "human_controlled_real") errors.push("source");
  if (item?.status !== "verified") errors.push("status");
  if (item?.mock_used !== false) errors.push("mock_used");
  if (item?.preseeded_account_used !== false) errors.push("preseeded_account_used");
  for (const [name, auth] of [["ordinary", ordinary], ["admin", admin]]) {
    if (auth?.status !== "passed") errors.push(`${name}.status`);
    if (auth?.chain !== "formal") errors.push(`${name}.chain`);
    if (auth?.verification_code_source !== "real_delivery") errors.push(`${name}.verification_code_source`);
  }
  return errorList(errors);
}

export function validateRedaction(value, serializedEvidence = "") {
  const item = object(value);
  const errors = [];
  if (item?.schema_version !== "1.0") errors.push("schema_version");
  if (item?.status !== "passed") errors.push("status");
  if (item?.forbidden_matches !== 0) errors.push("forbidden_matches");
  if (item?.credentials_in_evidence !== false) errors.push("credentials_in_evidence");
  if (item?.mailboxes_in_evidence !== false) errors.push("mailboxes_in_evidence");
  if (item?.private_content_in_evidence !== false) errors.push("private_content_in_evidence");
  if (item?.absolute_paths_in_evidence !== false) errors.push("absolute_paths_in_evidence");
  if (emailPattern.test(serializedEvidence)) errors.push("email_value");
  if (absolutePathPattern.test(serializedEvidence)) errors.push("absolute_path");
  if (sensitiveKeyPattern.test(serializedEvidence)) errors.push("sensitive_value");
  return errorList(errors);
}

export function validateCandidateReference(record) {
  try {
    validateReleaseCandidateRecord(record);
  } catch (error) {
    return [error instanceof Error ? "candidate_record_invalid" : "candidate_record_invalid"];
  }
  const errors = [];
  if (record.build_commit !== EXPECTED_WP7_01_COMMIT) errors.push("candidate_build_commit");
  const versions = new Map((record.browsers ?? []).map((browser) => [browser.brand, browser.full_version]));
  if (versions.get("Google Chrome") !== "150.0.7871.187") errors.push("chrome_full_version");
  if (versions.get("Microsoft Edge") !== "151.0.4129.59") errors.push("edge_full_version");
  return errorList(errors);
}

export function readJson(path) {
  if (!path || !existsSync(path)) return undefined;
  try {
    return JSON.parse(readFileSync(path, "utf8"));
  } catch {
    return undefined;
  }
}

export function fileSha256(path) {
  return createHash("sha256").update(readFileSync(path)).digest("hex").toUpperCase();
}

export function validateResendEvidence({ candidate, domainCheck, deliverySummary, authResult, redaction }) {
  const serializedEvidence = JSON.stringify({ domainCheck, deliverySummary, authResult });
  const errors = [
    ...validateCandidateReference(candidate),
    ...validateDomainCheck(domainCheck),
    ...validateDeliverySummary(deliverySummary),
    ...validateAuthResult(authResult),
    ...validateRedaction(redaction, serializedEvidence),
  ];
  return errorList(errors);
}
