/**
 * GET /api/content-briefs/brand-profile?brandId=X
 *
 * Returns brand profile data needed to pre-populate content brief
 * inputs. Beyond the raw BrandProfile fields, it now also returns:
 *
 *   • specialtyContext  — auto-detected from the brand's top GSC
 *     queries when BrandProfile.industry is missing or generic.
 *     Lets the AI prompt reference "cardiovascular practice" instead
 *     of "healthcare" without the user needing to edit the profile
 *     manually.
 *   • locations         — merged from BrandProfile + GBP + brand top-
 *     level location field, deduped.
 *   • topVisitorCities  — currently top countries because the
 *     TrackedSession schema only stores `country`. Caller can use
 *     this to suggest local content angles ("60% of visitors are
 *     in Houston" once city-level data lands).
 *   • topKeywords       — the brand's top 10 GSC queries by clicks,
 *     used both for specialty detection and as raw context for the
 *     AI brief prompt.
 *
 * Backwards-compatible: the original fields (name, domain, industry,
 * services, locations, targetAudience, shortDescription, brandVoice,
 * cta) are unchanged so existing callers keep working.
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { getBrandLocations } from "@/lib/brand-helpers";

export const dynamic = "force-dynamic";

/**
 * Auto-detect a brand's specialty from its top GSC queries. Returns
 * a short context string the AI brief prompt can paste into its
 * system message. Pure heuristic — keyword matches against a list
 * of medical specialties and broad industry verticals so the model
 * can over-rule it when context is clearer. Falls back to `null`
 * when no signals match.
 */
function detectSpecialty(topQueries: string[]): { label: string; topics: string[] } | null {
  const joined = topQueries.join(" ").toLowerCase();
  const buckets: Array<{ label: string; topics: string[]; pattern: RegExp }> = [
    {
      label: "cardiology / cardiovascular",
      topics: ["heart disease", "cardiology", "vascular health", "venous insufficiency", "circulation", "cholesterol"],
      pattern: /\b(cardiologist|cardiology|cardiovascular|heart\s|vascular|venous|insuficiencia|colesterol|circulaci[oó]n|valvular|arrhythmia|atrial)\b/,
    },
    {
      label: "dental",
      topics: ["general dentistry", "orthodontics", "implants", "cosmetic dentistry"],
      pattern: /\b(dentist|dental|orthodontist|braces|invisalign|implants?|teeth\s|dentista)\b/,
    },
    {
      label: "dermatology",
      topics: ["skin conditions", "cosmetic dermatology", "acne", "skin cancer"],
      pattern: /\b(dermatologist|dermatology|acne|botox|filler|skin\s|melanoma)\b/,
    },
    {
      label: "orthopedics",
      topics: ["joint replacement", "sports medicine", "spine", "physical therapy"],
      pattern: /\b(orthopedic|orthopaedic|knee\s|hip\s|spine|sports\s+medicine|joint\s+replacement)\b/,
    },
    {
      label: "law — personal injury",
      topics: ["car accidents", "premises liability", "wrongful death", "settlements"],
      pattern: /\b(personal\s+injury|car\s+accident|wrongful\s+death|injury\s+lawyer|abogado\s+de\s+accidentes)\b/,
    },
    {
      label: "law — family",
      topics: ["divorce", "custody", "alimony", "estate planning"],
      pattern: /\b(divorce|custody|family\s+law|alimony|estate\s+planning)\b/,
    },
    {
      label: "real estate",
      topics: ["homes for sale", "buyer's agent", "listings", "market reports"],
      pattern: /\b(real\s+estate|homes?\s+for\s+sale|buyer'?s?\s+agent|listings|realtor)\b/,
    },
    {
      label: "home services",
      topics: ["plumbing", "HVAC", "electrical", "roofing"],
      pattern: /\b(plumber|hvac|air\s+conditioning|roofing|electrician|water\s+heater)\b/,
    },
  ];
  for (const b of buckets) {
    if (b.pattern.test(joined)) return { label: b.label, topics: b.topics };
  }
  return null;
}

export async function GET(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const brandId = new URL(req.url).searchParams.get("brandId");
  if (!brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

  const brand = await prisma.brand.findUnique({
    where: { id: brandId },
    include: {
      organization: { include: { memberships: true } },
      profile: {
        select: { services: true, locations: true, industry: true, targetAudience: true, shortDescription: true, brandVoice: true },
      },
    },
  });
  if (!brand) return NextResponse.json({ error: "Brand not found" }, { status: 404 });
  if (!brand.organization.memberships.some((m) => m.userId === user.id)) {
    return NextResponse.json({ error: "Access denied" }, { status: 403 });
  }

  // ── Top GSC keywords for specialty detection + raw prompt context.
  // 90-day window so a thin-data brand still produces something.
  const since = new Date(Date.now() - 90 * 86_400_000);
  const topGscRows = await prisma.gscQuery.findMany({
    where: { brandId, date: { gte: since }, clicks: { gt: 0 } },
    orderBy: { clicks: "desc" },
    take: 30,
    select: { query: true, clicks: true, position: true },
  }).catch(() => []);

  // Dedup the query list (gscQuery rows can repeat across syncs) and
  // compress to top-10 by clicks.
  const queryMap = new Map<string, { query: string; clicks: number; position: number }>();
  for (const row of topGscRows) {
    const key = row.query.toLowerCase();
    const existing = queryMap.get(key);
    if (!existing || existing.clicks < row.clicks) queryMap.set(key, row);
  }
  const topKeywords = Array.from(queryMap.values()).sort((a, b) => b.clicks - a.clicks).slice(0, 10);

  // ── GBP locations + Site Tag visitor footprint.
  const [gbpLocations, site] = await Promise.all([
    prisma.gbpLocation.findMany({
      where: { brandId, isActive: true },
      select: { city: true, state: true, locationName: true },
    }).catch(() => []),
    prisma.trackedSite.findUnique({ where: { brandId }, select: { id: true } }).catch(() => null),
  ]);

  let topVisitorCities: Array<{ city: string; sessions: number }> = [];
  if (site?.id) {
    try {
      // TrackedSession.country only — no city in the schema today.
      // Surface what we have; the field name stays "topVisitorCities"
      // so the brief UI can rename without an API contract change.
      const grouped = await prisma.trackedSession.groupBy({
        by: ["country"],
        where: { trackedSiteId: site.id, country: { not: null }, startedAt: { gte: new Date(Date.now() - 30 * 86_400_000) } },
        _count: true,
        orderBy: { _count: { country: "desc" } },
        take: 5,
      });
      topVisitorCities = grouped
        .filter((g) => g.country)
        .map((g) => ({ city: g.country!, sessions: g._count }));
    } catch { /* tracker schema mismatch — skip */ }
  }

  // ── Merge locations from BrandProfile + GBP + Brand.locations[] + Brand.location.
  const locationSet = new Set<string>();
  for (const l of brand.profile?.locations ?? []) {
    if (typeof l === "string" && l.trim()) locationSet.add(l.trim());
  }
  for (const g of gbpLocations) {
    const label = [g.city, g.state].filter(Boolean).join(", ") || g.locationName;
    if (label) locationSet.add(label);
  }
  for (const l of getBrandLocations(brand)) locationSet.add(l);
  const locations = Array.from(locationSet);

  // ── Specialty detection. Skip when the user has set a specific
  // industry on the profile (their explicit value wins). Auto-detect
  // when the field is missing or set to a generic vertical like
  // "healthcare" / "general".
  const explicitIndustry = brand.profile?.industry || brand.industry || null;
  const isGeneric = !explicitIndustry || /^(healthcare|general|other|unknown)$/i.test(explicitIndustry);
  const detected = isGeneric ? detectSpecialty(topKeywords.map((k) => k.query)) : null;
  const specialty = detected
    ? {
        label: detected.label,
        topics: detected.topics,
        source: "auto_detected" as const,
        explicit: explicitIndustry,
      }
    : explicitIndustry
      ? { label: explicitIndustry, topics: [], source: "brand_profile" as const, explicit: explicitIndustry }
      : null;

  return NextResponse.json({
    name: brand.name,
    domain: brand.domain,
    industry: brand.industry || brand.profile?.industry || null,
    services: brand.profile?.services || [],
    locations,
    targetAudience: brand.profile?.targetAudience || null,
    shortDescription: brand.profile?.shortDescription || null,
    brandVoice: brand.profile?.brandVoice || null,
    cta: null, // no explicit CTA field — derived by the caller
    // ── New enrichment fields ──────────────────────────────────────
    specialty,
    topKeywords,
    topVisitorCities,
    gbpLocationCount: gbpLocations.length,
  });
}
