import { normalizeText } from "./utils.js";

export function normalizeLead(raw, context = {}) {
  const get = (...names) => {
    for (const name of names) {
      const value = raw[name] ?? raw[name.toLowerCase()] ?? raw[name.replace(/\s+/g, "_")];
      if (value) return normalizeText(value);
    }
    return "";
  };

  return {
    id: "",
    name: get("name", "title", "business name"),
    category: get("category", "type", "business type") || context.niche || "",
    address: get("address", "location"),
    city: context.city || "",
    phone: normalizePhone(get("phone", "phone number", "contact")),
    website: normalizeUrl(get("website", "url", "site")),
    rating: get("rating", "stars"),
    reviews: get("reviews", "review count"),
    email: get("email", "emails"),
    country: context.countryScope || "United States",
    sourceQuery: context.query || "",
    source: "google-maps-scrapper"
  };
}

export function leadKey(lead) {
  return [
    lead.website && lead.website.toLowerCase(),
    lead.phone,
    `${lead.name}|${lead.address}`.toLowerCase()
  ].find(Boolean);
}

export function detectFailure({ stage, rows, leads, error, target }) {
  if (error) {
    return classifyFailure(error);
  }
  if (stage === "discovery" && (!rows || rows.length === 0)) {
    return {
      detected: true,
      classification: "query issue",
      signal: "empty results",
      message: "Google Maps discovery returned no rows."
    };
  }
  if (stage === "discovery" && rows.length < Math.min(5, target || 5)) {
    return {
      detected: true,
      classification: "query issue",
      signal: "low coverage",
      message: "Discovery coverage was lower than expected."
    };
  }
  if (stage === "quality" && leads?.length) {
    const duplicateRate = 1 - new Set(leads.map(leadKey)).size / leads.length;
    if (duplicateRate > 0.35) {
      return {
        detected: true,
        classification: "schema issue",
        signal: "duplicate spike",
        message: `Duplicate rate was ${(duplicateRate * 100).toFixed(0)}%.`
      };
    }
  }
  return { detected: false };
}

export function classifyFailure(error) {
  const text = String(error.message || error || "").toLowerCase();
  if (text.includes("missing") || text.includes("not found") || text.includes("enoent")) {
    return { detected: true, classification: "tool issue", signal: "missing dependency", message: String(error.message || error) };
  }
  if (text.includes("timeout")) {
    return { detected: true, classification: "website issue", signal: "timeout", message: String(error.message || error) };
  }
  if (text.includes("selector") || text.includes("xpath") || text.includes("dom")) {
    return { detected: true, classification: "parser issue", signal: "selector failure", message: String(error.message || error) };
  }
  if (text.includes("invalid") || text.includes("schema")) {
    return { detected: true, classification: "schema issue", signal: "invalid data", message: String(error.message || error) };
  }
  return { detected: true, classification: "tool issue", signal: "runtime error", message: String(error.message || error) };
}

export function normalizePhone(value) {
  const text = normalizeText(value);
  if (!text) return "";
  const kept = text.replace(/[^\d+() -]/g, "");
  const digits = kept.replace(/\D/g, "");
  return digits.length >= 7 ? kept : "";
}

export function normalizeUrl(value) {
  const text = normalizeText(value);
  if (!text) return "";
  try {
    return new URL(text.startsWith("http") ? text : `https://${text}`).toString();
  } catch {
    return "";
  }
}
