/**
 * POST /api/gbp/discover
 *
 * Two modes:
 *   preview=true (or no selectedLocationIds): discovers all locations
 *     from the Google account, returns them WITHOUT creating records.
 *   selectedLocationIds provided: creates GbpLocation records only
 *     for the selected Google location IDs.
 *
 * Flow: accounts.list → get account name → locations.list
 */
import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { getValidAccessToken } from "@/lib/services/integration-credentials";

export const dynamic = "force-dynamic";
export const maxDuration = 60;

const ACCOUNTS_URL = "https://mybusinessaccountmanagement.googleapis.com/v1/accounts";
const LOCATIONS_BASE = "https://mybusinessbusinessinformation.googleapis.com/v1";

export async function POST(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  const body = await req.json().catch(() => null) as { brandId?: string; selectedLocationIds?: string[]; preview?: boolean } | null;
  if (!body?.brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

  const brand = await prisma.brand.findUnique({ where: { id: body.brandId }, include: { organization: { include: { memberships: 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 });

  let token: string;
  try { token = await getValidAccessToken(body.brandId, "gbp"); }
  catch { return NextResponse.json({ error: "GBP not connected. Complete OAuth first." }, { status: 400 }); }

  // Step 1: List accounts to get the account name
  console.log("[GBP] Step 1: Listing accounts...");
  const accountsRes = await fetch(ACCOUNTS_URL, { headers: { Authorization: `Bearer ${token}` } });
  const accountsText = await accountsRes.text();
  console.log("[GBP] Accounts response status:", accountsRes.status);
  console.log("[GBP] Accounts response:", accountsText.slice(0, 500));

  if (!accountsRes.ok) {
    return NextResponse.json({ error: `Google Accounts API ${accountsRes.status}: ${accountsText.slice(0, 200)}` }, { status: 502 });
  }

  let accountsData: { accounts?: Array<{ name?: string; accountName?: string; type?: string }> };
  try { accountsData = JSON.parse(accountsText); } catch {
    return NextResponse.json({ error: "Invalid response from Google Accounts API" }, { status: 502 });
  }

  const accounts = accountsData.accounts ?? [];
  console.log("[GBP] Found accounts:", accounts.length, accounts.map((a) => `${a.name} (${a.accountName}, ${a.type})`));

  if (accounts.length === 0) {
    return NextResponse.json({ error: "No GBP accounts found for this Google account" }, { status: 404 });
  }

  // Step 2: List locations for each account
  const allLocations: Array<{
    googleLocationId: string; locationName: string; address: string | null;
    city: string | null; state: string | null; phone: string | null;
    website: string | null; category: string | null; placeId: string | null;
    latitude: number | null; longitude: number | null;
  }> = [];

  for (const account of accounts) {
    const accountName = account.name; // e.g. "accounts/123456789"
    if (!accountName) continue;

    const locUrl = `${LOCATIONS_BASE}/${accountName}/locations?readMask=name,title,storefrontAddress,phoneNumbers,websiteUri,primaryCategory,metadata&pageSize=100`;
    console.log("[GBP] Step 2: Listing locations for", accountName, "URL:", locUrl);

    const locRes = await fetch(locUrl, { headers: { Authorization: `Bearer ${token}` } });
    const locText = await locRes.text();
    console.log("[GBP] Locations response status:", locRes.status);
    console.log("[GBP] Locations response:", locText.slice(0, 800));

    if (!locRes.ok) {
      console.log("[GBP] Locations failed for", accountName, "— skipping");
      continue;
    }

    let locData: { locations?: Array<Record<string, unknown>> };
    try { locData = JSON.parse(locText); } catch { continue; }

    for (const loc of locData.locations ?? []) {
      const addr = loc.storefrontAddress as Record<string, unknown> | undefined;
      const phones = loc.phoneNumbers as { primaryPhone?: string } | undefined;
      const cat = loc.primaryCategory as { displayName?: string } | undefined;
      const meta = loc.metadata as { placeId?: string; latlng?: { latitude?: number; longitude?: number } } | undefined;
      const lines = addr?.addressLines as string[] | undefined;
      allLocations.push({
        googleLocationId: String(loc.name ?? ""),
        locationName: String(loc.title ?? loc.name ?? ""),
        address: lines?.join(", ") ?? null,
        city: (addr?.locality as string) ?? null,
        state: (addr?.administrativeArea as string) ?? null,
        phone: phones?.primaryPhone ?? null,
        website: (loc.websiteUri as string) ?? null,
        category: cat?.displayName ?? null,
        placeId: meta?.placeId ?? null,
        latitude: meta?.latlng?.latitude ?? null,
        longitude: meta?.latlng?.longitude ?? null,
      });
    }
  }

  console.log("[GBP] Total locations discovered:", allLocations.length);

  // Preview mode: return without saving
  if (body.preview || !body.selectedLocationIds) {
    return NextResponse.json({ locations: allLocations, total: allLocations.length });
  }

  // Save selected locations
  const selectedSet = new Set(body.selectedLocationIds);
  const toSave = allLocations.filter((l) => selectedSet.has(l.googleLocationId));
  let saved = 0;
  for (const loc of toSave) {
    await prisma.gbpLocation.upsert({
      where: { brandId_googleLocationId: { brandId: body.brandId, googleLocationId: loc.googleLocationId } },
      create: { brandId: body.brandId, ...loc },
      update: { locationName: loc.locationName, isActive: true },
    });
    saved++;
  }

  const savedLocations = await prisma.gbpLocation.findMany({ where: { brandId: body.brandId, isActive: true } });
  return NextResponse.json({ saved, locations: savedLocations });
}
