/**
 * GEO (Generative Engine Optimization) Analysis Service
 * ──────────────────────────────────────────────────────
 * Scores GBP locations for AI search readiness and extracts review
 * intelligence signals that influence how ChatGPT, Perplexity, Gemini,
 * and Claude surface local businesses in their answers.
 */

import { prisma } from "@/lib/prisma";
import { callLlm } from "@/lib/ai-avatar/llm-client";

// ─── Review intelligence extraction ────────────────────────────────────────

export interface ReviewIntelligence {
  topTerms: Array<{ term: string; count: number }>;
  serviceFrequency: Array<{ service: string; mentions: number }>;
  locationMentions: Array<{ area: string; count: number }>;
  trustSignals: { expertise: number; quality: number; comparison: number };
  suggestReviewTopics: string[];
}

export async function extractReviewIntelligence(locationId: string): Promise<ReviewIntelligence> {
  const reviews = await prisma.gbpReview.findMany({
    where: { locationId, comment: { not: null } },
    select: { comment: true, topics: true, rating: true },
    take: 200,
  });

  if (reviews.length === 0) {
    return { topTerms: [], serviceFrequency: [], locationMentions: [], trustSignals: { expertise: 0, quality: 0, comparison: 0 }, suggestReviewTopics: [] };
  }

  const allText = reviews.map((r) => r.comment || "").join(" ").toLowerCase();
  // Topic frequency from AI-classified topics
  const topicCounts = new Map<string, number>();
  for (const r of reviews) { for (const t of r.topics) { topicCounts.set(t, (topicCounts.get(t) || 0) + 1); } }
  const topTerms = [...topicCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20).map(([term, count]) => ({ term, count }));

  // Trust signal counting
  const expertiseRe = /\b(board certified|certified|licensed|experienced|expert|specialist|years experience|professional)\b/gi;
  const qualityRe = /\b(best|excellent|amazing|outstanding|wonderful|top notch|highly recommend|five star)\b/gi;
  const comparisonRe = /\b(better than|compared to|switched from|unlike other|stands out)\b/gi;

  const expertise = (allText.match(expertiseRe) || []).length;
  const quality = (allText.match(qualityRe) || []).length;
  const comparison = (allText.match(comparisonRe) || []).length;

  // Use Claude to extract services and locations from review corpus
  const result = await callLlm([
    { role: "system", content: "Extract structured data from reviews. Respond ONLY with JSON." },
    { role: "user", content: `From these ${reviews.length} reviews, extract:\n1. Services mentioned (medical procedures, services offered)\n2. Location/area mentions (cities, neighborhoods, landmarks)\n3. What services need more review mentions to improve AI visibility\n\nReview sample: "${allText.slice(0, 3000)}"\n\nReturn: {"services":[{"service":"...","mentions":N}],"locations":[{"area":"...","count":N}],"suggestTopics":["..."]}` },
  ], () => JSON.stringify({ services: [], locations: [], suggestTopics: [] }), { maxTokens: 1500 });

  let services: Array<{ service: string; mentions: number }> = [];
  let locations: Array<{ area: string; count: number }> = [];
  let suggestTopics: string[] = [];
  try {
    let s = result.reply.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
    const f = s.indexOf("{"), l = s.lastIndexOf("}");
    if (f >= 0 && l > f) s = s.slice(f, l + 1);
    const parsed = JSON.parse(s) as { services?: Array<{ service: string; mentions: number }>; locations?: Array<{ area: string; count: number }>; suggestTopics?: string[] };
    services = parsed.services ?? [];
    locations = parsed.locations ?? [];
    suggestTopics = parsed.suggestTopics ?? [];
  } catch { /* swallow */ }

  return { topTerms, serviceFrequency: services, locationMentions: locations, trustSignals: { expertise, quality, comparison }, suggestReviewTopics: suggestTopics };
}

// ─── GEO readiness scoring ──────────────────────────────────────────────────

export interface GeoScore {
  geoScore: number;
  strengths: string[];
  weaknesses: string[];
  recommendations: Array<{ action: string; impact: string; reason: string }>;
  suggestedSchema: string[];
  reviewStrategy: string;
  contentSuggestions: string[];
}

export async function analyzeGeoReadiness(locationId: string): Promise<GeoScore> {
  const loc = await prisma.gbpLocation.findUnique({ where: { id: locationId } });
  if (!loc) return emptyScore();

  const reviews = await prisma.gbpReview.findMany({
    where: { locationId }, select: { rating: true, sentiment: true, topics: true }, take: 100,
  });
  const topicCounts = new Map<string, number>();
  let posCount = 0, negCount = 0;
  for (const r of reviews) {
    if (r.sentiment === "positive") posCount++;
    if (r.sentiment === "negative") negCount++;
    for (const t of r.topics) topicCounts.set(t, (topicCounts.get(t) || 0) + 1);
  }
  const topTopics = [...topicCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([t]) => t);

  // Check for schema on the website via PageSEOSnapshot
  let hasSchema = false;
  if (loc.website) {
    const snap = await prisma.pageSEOSnapshot.findFirst({
      where: { brandId: loc.brandId, pageUrl: { contains: loc.website.replace(/^https?:\/\/(www\.)?/, "").split("/")[0] } },
      select: { hasSchema: true, schemaTypes: true },
    });
    hasSchema = snap?.hasSchema ?? false;
  }

  const result = await callLlm([
    { role: "system", content: "You are a GEO (Generative Engine Optimization) analyst. Respond ONLY with JSON." },
    { role: "user", content: `Analyze this Google Business Profile for AI search visibility:\nBusiness: ${loc.locationName}, ${loc.category}, ${loc.city} ${loc.state}\nRating: ${loc.avgRating} (${loc.totalReviews} reviews)\nTop review topics: ${topTopics.join(", ")}\nSentiment: ${posCount} positive, ${negCount} negative\nWebsite: ${loc.website || "none"}\nHas schema: ${hasSchema}\n\nReturn JSON: {"geoScore":0-100,"strengths":["..."],"weaknesses":["..."],"recommendations":[{"action":"...","impact":"high|medium|low","reason":"..."}],"suggestedSchema":["LocalBusiness"],"reviewStrategy":"...","contentSuggestions":["..."]}` },
  ], () => JSON.stringify(emptyScore()), { maxTokens: 2000 });

  try {
    let s = result.reply.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
    const f = s.indexOf("{"), l = s.lastIndexOf("}");
    if (f >= 0 && l > f) s = s.slice(f, l + 1);
    return JSON.parse(s) as GeoScore;
  } catch { return emptyScore(); }
}

function emptyScore(): GeoScore {
  return { geoScore: 0, strengths: [], weaknesses: [], recommendations: [], suggestedSchema: [], reviewStrategy: "", contentSuggestions: [] };
}
