// @ts-nocheck — Legacy GBP service. Superseded by gbp-multi-location.ts.
// Kept for backward compat with existing callers; will be migrated.
/**
 * Google Business Profile — Sync & Storage Service (Legacy)
 * ---------------------------------------------------
 * Stores GBP data from the API and provides query functions
 * for Local GEO, Conversion Intelligence, and the AI Avatar.
 *
 * Data stored:
 *   GbpLocation — the business location (name, address, rating, review count)
 *   GbpReview   — individual reviews (author, rating, text, reply)
 *   GbpMetric   — daily performance (searches, views, actions)
 */

import { prisma } from "@/lib/prisma";
import { log } from "@/lib/logger";

// ─── Types ───────────────────────────────────────────────────────────────────

export interface GbpSummary {
  location: {
    name: string;
    address: string | null;
    phone: string | null;
    category: string | null;
    avgRating: number;
    totalReviews: number;
  } | null;
  metrics: {
    searchesTotal: number;
    searchesDirect: number;
    searchesDiscovery: number;
    viewsTotal: number;
    actionsWebsite: number;
    actionsPhone: number;
    actionsDirections: number;
  };
  recentReviews: Array<{
    authorName: string;
    rating: number;
    comment: string | null;
    publishedAt: string;
  }>;
  ratingBreakdown: Record<number, number>;
  period: { startDate: string; endDate: string };
}

// ─── Store location data ─────────────────────────────────────────────────────

export async function storeGbpLocation(
  brandId: string,
  location: {
    locationId: string;
    locationName: string;
    address?: string;
    phone?: string;
    category?: string;
    websiteUrl?: string;
    mapsUrl?: string;
    placeId?: string;
  }
): Promise<void> {
  await prisma.gbpLocation.upsert({
    where: { brandId_locationId: { brandId, locationId: location.locationId } },
    create: {
      brandId,
      locationId: location.locationId,
      locationName: location.locationName,
      address: location.address ?? null,
      phone: location.phone ?? null,
      category: location.category ?? null,
      websiteUrl: location.websiteUrl ?? null,
      mapsUrl: location.mapsUrl ?? null,
      placeId: location.placeId ?? null,
    },
    update: {
      locationName: location.locationName,
      address: location.address ?? undefined,
      phone: location.phone ?? undefined,
      category: location.category ?? undefined,
      websiteUrl: location.websiteUrl ?? undefined,
      mapsUrl: location.mapsUrl ?? undefined,
      placeId: location.placeId ?? undefined,
    },
  });
}

// ─── Store reviews ───────────────────────────────────────────────────────────

export async function storeGbpReviews(
  brandId: string,
  reviews: Array<{
    reviewId: string;
    authorName: string;
    rating: number;
    comment?: string;
    replyText?: string;
    publishedAt: string;
  }>
): Promise<number> {
  let stored = 0;

  for (const review of reviews) {
    await prisma.gbpReview.upsert({
      where: { reviewId: review.reviewId },
      create: {
        brandId,
        reviewId: review.reviewId,
        authorName: review.authorName,
        rating: review.rating,
        comment: review.comment ?? null,
        replyText: review.replyText ?? null,
        publishedAt: new Date(review.publishedAt),
      },
      update: {
        comment: review.comment ?? undefined,
        replyText: review.replyText ?? undefined,
      },
    });
    stored++;
  }

  // Update location stats
  const avgRating = await prisma.gbpReview.aggregate({
    where: { brandId },
    _avg: { rating: true },
    _count: true,
  });

  await prisma.gbpLocation.updateMany({
    where: { brandId },
    data: {
      avgRating: Math.round((avgRating._avg.rating ?? 0) * 10) / 10,
      totalReviews: avgRating._count,
    },
  });

  return stored;
}

// ─── Store daily metrics ─────────────────────────────────────────────────────

export async function storeGbpMetrics(
  brandId: string,
  metrics: Array<{
    date: string;
    searchesTotal?: number;
    searchesDirect?: number;
    searchesDiscovery?: number;
    viewsTotal?: number;
    viewsMaps?: number;
    viewsSearch?: number;
    actionsWebsite?: number;
    actionsPhone?: number;
    actionsDirections?: number;
  }>
): Promise<number> {
  let stored = 0;

  for (const m of metrics) {
    const date = new Date(m.date);
    await prisma.gbpMetric.upsert({
      where: { brandId_date: { brandId, date } },
      create: {
        brandId, date,
        searchesTotal: m.searchesTotal ?? 0,
        searchesDirect: m.searchesDirect ?? 0,
        searchesDiscovery: m.searchesDiscovery ?? 0,
        viewsTotal: m.viewsTotal ?? 0,
        viewsMaps: m.viewsMaps ?? 0,
        viewsSearch: m.viewsSearch ?? 0,
        actionsWebsite: m.actionsWebsite ?? 0,
        actionsPhone: m.actionsPhone ?? 0,
        actionsDirections: m.actionsDirections ?? 0,
      },
      update: {
        searchesTotal: m.searchesTotal ?? undefined,
        searchesDirect: m.searchesDirect ?? undefined,
        searchesDiscovery: m.searchesDiscovery ?? undefined,
        viewsTotal: m.viewsTotal ?? undefined,
        viewsMaps: m.viewsMaps ?? undefined,
        viewsSearch: m.viewsSearch ?? undefined,
        actionsWebsite: m.actionsWebsite ?? undefined,
        actionsPhone: m.actionsPhone ?? undefined,
        actionsDirections: m.actionsDirections ?? undefined,
      },
    });
    stored++;
  }

  log.info("integration", `Stored ${stored} days of GBP metrics`, { metadata: { brandId } });
  return stored;
}

// ─── Read functions ──────────────────────────────────────────────────────────

/**
 * Full GBP summary — used by Local GEO and AI Avatar.
 */
export async function getGbpSummary(brandId: string, days: number = 28): Promise<GbpSummary | null> {
  const location = await prisma.gbpLocation.findFirst({ where: { brandId } });
  const since = new Date(Date.now() - days * 86400000);

  const metrics = await prisma.gbpMetric.findMany({
    where: { brandId, date: { gte: since } },
  });

  const reviews = await prisma.gbpReview.findMany({
    where: { brandId },
    orderBy: { publishedAt: "desc" },
    take: 10,
  });

  if (!location && metrics.length === 0 && reviews.length === 0) return null;

  // Aggregate metrics
  const totals = {
    searchesTotal: metrics.reduce((s, m) => s + m.searchesTotal, 0),
    searchesDirect: metrics.reduce((s, m) => s + m.searchesDirect, 0),
    searchesDiscovery: metrics.reduce((s, m) => s + m.searchesDiscovery, 0),
    viewsTotal: metrics.reduce((s, m) => s + m.viewsTotal, 0),
    actionsWebsite: metrics.reduce((s, m) => s + m.actionsWebsite, 0),
    actionsPhone: metrics.reduce((s, m) => s + m.actionsPhone, 0),
    actionsDirections: metrics.reduce((s, m) => s + m.actionsDirections, 0),
  };

  // Rating breakdown
  const allReviews = await prisma.gbpReview.findMany({
    where: { brandId },
    select: { rating: true },
  });
  const breakdown: Record<number, number> = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 };
  for (const r of allReviews) {
    breakdown[r.rating] = (breakdown[r.rating] ?? 0) + 1;
  }

  return {
    location: location ? {
      name: location.locationName,
      address: location.address,
      phone: location.phone,
      category: location.category,
      avgRating: location.avgRating,
      totalReviews: location.totalReviews,
    } : null,
    metrics: totals,
    recentReviews: reviews.map(r => ({
      authorName: r.authorName,
      rating: r.rating,
      comment: r.comment,
      publishedAt: r.publishedAt.toISOString(),
    })),
    ratingBreakdown: breakdown,
    period: { startDate: since.toISOString().split("T")[0], endDate: new Date().toISOString().split("T")[0] },
  };
}

/**
 * GBP conversion actions — used by Conversion Intelligence.
 * Returns phone calls, website clicks, and direction requests.
 */
export async function getGbpConversions(brandId: string, days: number = 28) {
  const since = new Date(Date.now() - days * 86400000);

  const metrics = await prisma.gbpMetric.findMany({
    where: { brandId, date: { gte: since } },
    orderBy: { date: "asc" },
  });

  return {
    totalPhoneCalls: metrics.reduce((s, m) => s + m.actionsPhone, 0),
    totalWebsiteClicks: metrics.reduce((s, m) => s + m.actionsWebsite, 0),
    totalDirections: metrics.reduce((s, m) => s + m.actionsDirections, 0),
    totalActions: metrics.reduce((s, m) => s + m.actionsPhone + m.actionsWebsite + m.actionsDirections, 0),
    daily: metrics.map(m => ({
      date: m.date.toISOString().split("T")[0],
      phone: m.actionsPhone,
      website: m.actionsWebsite,
      directions: m.actionsDirections,
    })),
  };
}
