import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { getCurrentUser, requirePermission } from "@/lib/auth";
import { connectIntegration, syncIntegration, disconnectIntegration } from "@/lib/integrations";
import { checkConnectionHealth } from "@/lib/services/integration-credentials";
import { log } from "@/lib/logger";

/**
 * GET /api/integrations?brandId=xxx
 * Returns all integrations for a brand with their connection status.
 * Requires admin or owner role.
 */
export const dynamic = "force-dynamic";

export async function GET(req: Request) {
  const denied = await requirePermission("integrations");
  if (denied) return denied;

  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

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

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

  const brand = await prisma.brand.findUnique({
    where: { id: brandId },
    include: { organization: { include: { memberships: true } } },
  });

  if (!brand) return NextResponse.json({ error: "Brand not found" }, { status: 404 });

  const isMember = brand.organization.memberships.some((m) => m.userId === user.id);
  if (!isMember) return NextResponse.json({ error: "Access denied" }, { status: 403 });

  const integrations = await prisma.brandIntegration.findMany({
    where: { brandId },
    orderBy: { createdAt: "desc" },
  });

  // Enrich with health status for each integration
  const enriched = await Promise.all(
    integrations.map(async (i) => {
      const health = await checkConnectionHealth(brandId, i.integrationId);
      return {
        id: i.id,
        integrationId: i.integrationId,
        connected: i.connected,
        status: health.status,
        lastSynced: i.lastSynced?.toISOString() ?? null,
        syncError: i.syncError,
        syncRetryCount: i.syncRetryCount,
        nextRetryAt: i.nextRetryAt?.toISOString() ?? null,
        tokenExpired: health.tokenExpired,
        credentialsMeta: i.credentialsMeta,
        healthMessage: health.message,
      };
    })
  );

  log.apiRequest("/api/integrations", "GET", 200, 0, { userId: user.id });
  return NextResponse.json(enriched);
}

/**
 * POST /api/integrations
 * Connect, disconnect, or sync an integration for a brand.
 * Body: { brandId, integrationId, action: "connect" | "disconnect" | "sync" }
 */
export async function POST(req: Request) {
  const denied = await requirePermission("integrations");
  if (denied) return denied;

  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  try {
    const { brandId, integrationId, action, credentials, force } = await req.json();

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

    // Verify access
    const brand = await prisma.brand.findUnique({
      where: { id: brandId },
      include: { organization: { include: { memberships: true } } },
    });

    if (!brand) return NextResponse.json({ error: "Brand not found" }, { status: 404 });

    const isMember = brand.organization.memberships.some((m) => m.userId === user.id);
    if (!isMember) return NextResponse.json({ error: "Access denied" }, { status: 403 });

    // ── CONNECT ──
    if (action === "connect") {
      // Ensure the integration row exists
      await prisma.brandIntegration.upsert({
        where: { brandId_integrationId: { brandId, integrationId } },
        update: { connected: true, status: "syncing", syncError: null },
        create: { brandId, integrationId, connected: true, status: "syncing" },
      });

      const result = await connectIntegration(brandId, integrationId, credentials);

      if (!result.success) {
        await prisma.brandIntegration.update({
          where: { brandId_integrationId: { brandId, integrationId } },
          data: { status: "error", syncError: result.message },
        });
      }

      const updated = await prisma.brandIntegration.findUnique({
        where: { brandId_integrationId: { brandId, integrationId } },
      });
      return NextResponse.json({ integration: updated, result });
    }

    // ── DISCONNECT ──
    if (action === "disconnect") {
      const result = await disconnectIntegration(brandId, integrationId);

      await prisma.brandIntegration.update({
        where: { brandId_integrationId: { brandId, integrationId } },
        data: {
          connected: false,
          status: "idle",
          syncError: null,
          syncRetryCount: 0,
          nextRetryAt: null,
          credentialsEnc: null,
          credentialsMeta: {},
          tokenExpiresAt: null,
        },
      });

      const updated = await prisma.brandIntegration.findUnique({
        where: { brandId_integrationId: { brandId, integrationId } },
      });
      return NextResponse.json({ integration: updated, result });
    }

    // ── SYNC NOW ──
    // Pass `force: true` to trigger a full re-sync: the service wipes its
    // existing cached data and pulls the full historical window (90 days for
    // GSC). Incremental syncs run without the flag.
    if (action === "sync") {
      const existing = await prisma.brandIntegration.findUnique({
        where: { brandId_integrationId: { brandId, integrationId } },
      });

      if (!existing?.connected) {
        return NextResponse.json({ error: "Integration is not connected" }, { status: 400 });
      }

      await prisma.brandIntegration.update({
        where: { id: existing.id },
        data: { status: "syncing", syncError: null },
      });

      const result = await syncIntegration(brandId, integrationId, { force: force === true });

      const updated = await prisma.brandIntegration.findUnique({
        where: { id: existing.id },
      });
      return NextResponse.json({ integration: updated, result });
    }

    // ── HEALTH CHECK ──
    if (action === "health") {
      const health = await checkConnectionHealth(brandId, integrationId);
      return NextResponse.json(health);
    }

    return NextResponse.json({ error: "action must be 'connect', 'disconnect', 'sync', or 'health'" }, { status: 400 });

  } catch (e) {
    const msg = e instanceof Error ? e.message : "Something went wrong";
    log.error("integration", `Integration API error: ${msg}`, {
      path: "/api/integrations",
      metadata: { error: msg, stack: e instanceof Error ? e.stack : undefined },
    });
    return NextResponse.json({ error: msg }, { status: 500 });
  }
}
