/**
 * GET /api/integrations/properties?brandId=xxx&service=ga4
 * ----------------------------------------------------------
 * After OAuth, fetches the user's available properties from Google.
 * - GA4: lists analytics properties
 * - GSC: lists verified sites
 *
 * POST /api/integrations/properties
 * ----------------------------------------------------------
 * Saves the selected property ID to the brand's credentials.
 * Body: { brandId, service, propertyId, propertyName }
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { getCredentials, saveCredentials, getValidAccessToken } from "@/lib/services/integration-credentials";
import { apiCall } from "@/lib/integrations/types";
import { log } from "@/lib/logger";

export const dynamic = "force-dynamic";

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

  const { searchParams } = new URL(req.url);
  const brandId = searchParams.get("brandId");
  const service = searchParams.get("service");

  if (!brandId || !service) {
    return NextResponse.json({ error: "brandId and service required" }, { status: 400 });
  }

  let creds;
  try {
    creds = await getCredentials(brandId, service);
  } catch (err) {
    const msg = err instanceof Error ? err.message : "unknown";
    return NextResponse.json({ error: `Credential read failed: ${msg}`, properties: [] }, { status: 200 });
  }

  if (!creds?.accessToken) {
    // Check if the row exists but credentials are empty
    const row = await prisma.brandIntegration.findUnique({
      where: { brandId_integrationId: { brandId, integrationId: service } },
      select: { credentialsEnc: true, connected: true },
    });
    return NextResponse.json({
      error: `No access token. Connected: ${row?.connected}, Has encrypted data: ${!!row?.credentialsEnc}`,
      properties: [],
    }, { status: 200 });
  }

  // Refresh the token if expired. Property pickers can be opened long after
  // OAuth completes, so the original access_token may already be stale.
  let accessToken: string;
  try {
    accessToken = await getValidAccessToken(brandId, service);
  } catch (err) {
    const msg = err instanceof Error ? err.message : "Reconnect to continue";
    return NextResponse.json({ error: msg, properties: [] }, { status: 200 });
  }

  // ── GA4: list analytics accounts and properties ──
  if (service === "ga4") {
    const res = await apiCall(
      "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
      { bearerToken: accessToken }
    );

    if (!res.ok) {
      log.error("integration", `Failed to list GA4 properties: ${res.error}`);
      return NextResponse.json({ error: res.error, properties: [] }, { status: 200 });
    }

    const data = res.data as { accountSummaries?: Array<{ account: string; displayName: string; propertySummaries?: Array<{ property: string; displayName: string }> }> };

    const properties = (data.accountSummaries ?? []).flatMap(account =>
      (account.propertySummaries ?? []).map(prop => ({
        id: prop.property.replace("properties/", ""),
        name: prop.displayName,
        account: account.displayName,
        fullId: prop.property,
      }))
    );

    const currentId = (creds.propertyId as string | undefined) || null;
    return NextResponse.json({ properties, currentId });
  }

  // ── GSC: list verified sites ──
  if (service === "gsc") {
    log.info("integration", `Loading GSC sites for brand ${brandId}`, {
      metadata: { brandId, hasToken: !!creds.accessToken },
    });

    const res = await apiCall(
      "https://www.googleapis.com/webmasters/v3/sites",
      { bearerToken: accessToken }
    );

    if (!res.ok) {
      log.error("integration", `Failed to list GSC sites: ${res.error}`, {
        metadata: { brandId, status: res.status, error: res.error },
      });
      return NextResponse.json({ error: `GSC API error: ${res.error}`, properties: [] }, { status: 200 });
    }

    const data = res.data as { siteEntry?: Array<{ siteUrl: string; permissionLevel: string }> };

    log.info("integration", `GSC returned ${data.siteEntry?.length ?? 0} sites`, {
      metadata: { brandId, count: data.siteEntry?.length ?? 0 },
    });

    const properties = (data.siteEntry ?? []).map(site => ({
      id: site.siteUrl,
      name: site.siteUrl,
      account: site.permissionLevel,
      fullId: site.siteUrl,
    }));

    // Pass the currently-selected siteUrl back so the picker can
    // highlight the auto-matched row the callback pre-selected.
    const currentId = (creds.siteUrl as string | undefined) || (creds.accountId as string | undefined) || (creds.propertyId as string | undefined) || null;
    return NextResponse.json({ properties, currentId });
  }

  return NextResponse.json({ properties: [] });
}

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

  const { brandId, service, propertyId, propertyName } = await req.json();

  if (!brandId || !service || !propertyId) {
    return NextResponse.json({ error: "brandId, service, and propertyId required" }, { status: 400 });
  }

  // Get existing credentials and add the property ID
  const creds = await getCredentials(brandId, service);
  if (!creds) {
    return NextResponse.json({ error: "No credentials found" }, { status: 400 });
  }

  // Save the property ID into the credentials
  await saveCredentials(brandId, service, {
    ...creds,
    propertyId,
    propertyName,
    // For GSC, also save as siteUrl and accountId
    ...(service === "gsc" ? { siteUrl: propertyId, accountId: propertyId } : {}),
  });

  log.info("integration", `Property selected: ${propertyName} (${propertyId})`, {
    metadata: { brandId, service, propertyId },
  });

  return NextResponse.json({ ok: true, propertyId, propertyName });
}
