import type { TrackedSession } from "@prisma/client";

// Only the fields scoreSession actually reads from SiteEvent rows.
// Using a structural subset avoids pulling eventData (heavy JSONB) in callers.
type SiteEventForScoring = { eventType: string; timestamp: Date };

export interface ContributingFactor {
  signal: string;
  weight: number;
  source: "engagement" | "intent" | "channel" | "negative";
}

export interface SessionScoreResult {
  score: number;
  contributingFactors: ContributingFactor[];
}

export interface PageVisit {
  pageUrl: string;
  timeOnPage?: number;   // seconds
  maxScrollPercent?: number;
}

// Pages that signal high purchase/conversion intent
const HIGH_CONVERTING_PATTERNS = [
  "/pricing", "/checkout", "/contact", "/demo", "/trial",
  "/get-started", "/signup", "/register", "/buy", "/order",
  "/schedule", "/book", "/quote", "/consult",
];

function isHighConvertingPage(url: string): boolean {
  try {
    const path = new URL(url).pathname.toLowerCase();
    return HIGH_CONVERTING_PATTERNS.some((p) => path.includes(p));
  } catch {
    const lower = url.toLowerCase();
    return HIGH_CONVERTING_PATTERNS.some((p) => lower.includes(p));
  }
}

function isAiReferrer(referrer: string | null | undefined): boolean {
  if (!referrer) return false;
  const lower = referrer.toLowerCase();
  return (
    lower.includes("chatgpt") ||
    lower.includes("perplexity") ||
    lower.includes("gemini") ||
    lower.includes("bard") ||
    lower.includes("chat.openai") ||
    lower.includes("you.com") ||
    lower.includes("phind")
  );
}

function isCopilotReferrer(referrer: string | null | undefined, msclkid: string | null | undefined): boolean {
  if (msclkid) return true;
  if (!referrer) return false;
  const lower = referrer.toLowerCase();
  return lower.includes("bing") || lower.includes("copilot.microsoft");
}

function isOrganicBrandedSearch(referrer: string | null | undefined, utmMedium: string | null | undefined): boolean {
  if (!referrer) return false;
  const lower = referrer.toLowerCase();
  const isSearchEngine = lower.includes("google.") || lower.includes("bing.") || lower.includes("yahoo.");
  const isOrganic = !utmMedium || utmMedium === "organic";
  return isSearchEngine && isOrganic;
}

function sessionAgeSeconds(session: TrackedSession): number {
  return (Date.now() - session.startedAt.getTime()) / 1000;
}

export function scoreSession(
  session: TrackedSession,
  recentEvents: SiteEventForScoring[],
  pageVisits: PageVisit[],
): SessionScoreResult {
  const factors: ContributingFactor[] = [];
  let score = 10; // base score

  const ageSeconds = sessionAgeSeconds(session);
  const isMobile = session.device === "mobile";

  // ── Negative: bounce / minimal engagement ──────────────────────────────────
  if (ageSeconds < 5 && session.pageCount <= 1) {
    factors.push({ signal: "Immediate bounce (<5s)", weight: -20, source: "negative" });
    score -= 20;
  } else if (ageSeconds < 10 && isMobile && session.pageCount <= 1) {
    factors.push({ signal: "Mobile micro-session (<10s)", weight: -15, source: "negative" });
    score -= 15;
  }

  const eventTypes = recentEvents.map((e) => e.eventType);
  const hasAnyInteraction = eventTypes.some((t) =>
    ["click", "form_filled", "form_started", "phone_click", "rage_click", "scroll"].includes(t),
  );

  if (!hasAnyInteraction && ageSeconds > 30) {
    factors.push({ signal: "No interaction after 30s", weight: -10, source: "negative" });
    score -= 10;
  }

  // ── Engagement: time on site ───────────────────────────────────────────────
  if (ageSeconds >= 300) {
    factors.push({ signal: "5+ minutes on site", weight: 20, source: "engagement" });
    score += 20;
  } else if (ageSeconds >= 120) {
    factors.push({ signal: "2–5 minutes on site", weight: 15, source: "engagement" });
    score += 15;
  } else if (ageSeconds >= 60) {
    factors.push({ signal: "1–2 minutes on site", weight: 10, source: "engagement" });
    score += 10;
  }

  // ── Engagement: pages viewed ───────────────────────────────────────────────
  if (session.pageCount >= 5) {
    factors.push({ signal: "5+ pages viewed", weight: 15, source: "engagement" });
    score += 15;
  } else if (session.pageCount >= 3) {
    factors.push({ signal: "3–4 pages viewed", weight: 10, source: "engagement" });
    score += 10;
  }

  // ── Engagement: scroll depth ───────────────────────────────────────────────
  const maxScroll = pageVisits.reduce((m, v) => Math.max(m, v.maxScrollPercent ?? 0), 0);
  if (maxScroll >= 80) {
    factors.push({ signal: "Deep scroll (80%+)", weight: 15, source: "engagement" });
    score += 15;
  } else if (maxScroll >= 50) {
    factors.push({ signal: "Mid-page scroll (50–80%)", weight: 10, source: "engagement" });
    score += 10;
  }

  // ── Engagement: time on page ───────────────────────────────────────────────
  const maxTimeOnPage = pageVisits.reduce((m, v) => Math.max(m, v.timeOnPage ?? 0), 0);
  if (maxTimeOnPage >= 90) {
    factors.push({ signal: "90s+ on a single page", weight: 10, source: "engagement" });
    score += 10;
  }

  // ── Intent: high-converting page visited ──────────────────────────────────
  const visitedHighConverting =
    pageVisits.some((v) => isHighConvertingPage(v.pageUrl)) ||
    isHighConvertingPage(session.entryPage);
  if (visitedHighConverting) {
    factors.push({ signal: "Visited high-intent page (pricing/contact/demo)", weight: 10, source: "intent" });
    score += 10;
  }

  // ── Intent: form interaction ───────────────────────────────────────────────
  if (eventTypes.includes("form_filled") || eventTypes.includes("form_submitted")) {
    factors.push({ signal: "Form submission detected", weight: 20, source: "intent" });
    score += 20;
  } else if (eventTypes.includes("form_started") || eventTypes.includes("form_focused")) {
    factors.push({ signal: "Form interaction started", weight: 10, source: "intent" });
    score += 10;
  }

  // ── Intent: phone click ────────────────────────────────────────────────────
  if (eventTypes.includes("phone_click") || eventTypes.includes("tel_click")) {
    factors.push({ signal: "Phone number clicked", weight: 25, source: "intent" });
    score += 25;
  }

  // ── Channel: AI referral ───────────────────────────────────────────────────
  if (isCopilotReferrer(session.referrer, session.msclkid)) {
    factors.push({ signal: "Referred by Microsoft Copilot/Bing", weight: 15, source: "channel" });
    score += 15;
  } else if (isAiReferrer(session.referrer)) {
    factors.push({ signal: "Referred by AI assistant", weight: 10, source: "channel" });
    score += 10;
  }

  // ── Channel: organic branded search ───────────────────────────────────────
  if (isOrganicBrandedSearch(session.referrer, session.utmMedium)) {
    factors.push({ signal: "Organic search referral", weight: 20, source: "channel" });
    score += 20;
  }

  // Cap 0–100
  score = Math.max(0, Math.min(100, score));

  return { score: Math.round(score), contributingFactors: factors };
}

export function scoreBand(score: number): "very_low" | "low" | "moderate" | "high" | "very_high" {
  if (score <= 20) return "very_low";
  if (score <= 40) return "low";
  if (score <= 60) return "moderate";
  if (score <= 80) return "high";
  return "very_high";
}

export function scoreBandLabel(band: ReturnType<typeof scoreBand>): string {
  const labels = {
    very_low: "Very Low",
    low: "Low",
    moderate: "Moderate",
    high: "High",
    very_high: "Very High",
  } as const;
  return labels[band];
}
