import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/db";

const OAUTH_CONFIGS: Record<
  string,
  {
    tokenUrl: string;
    clientIdEnv: string;
    clientSecretEnv: string;
  }
> = {
  planning_center: {
    tokenUrl: "https://api.planningcenteronline.com/oauth/token",
    clientIdEnv: "PCO_CLIENT_ID",
    clientSecretEnv: "PCO_CLIENT_SECRET",
  },
  google_sheets: {
    tokenUrl: "https://oauth2.googleapis.com/token",
    clientIdEnv: "GOOGLE_CLIENT_ID",
    clientSecretEnv: "GOOGLE_CLIENT_SECRET",
  },
};

export async function GET(
  req: NextRequest,
  { params }: { params: Promise<{ provider: string }> }
) {
  try {
    const { provider } = await params;
    const oauthConfig = OAUTH_CONFIGS[provider];
    if (!oauthConfig) {
      return NextResponse.redirect(
        new URL("/settings/integrations?error=unsupported_provider", req.url)
      );
    }

    const code = req.nextUrl.searchParams.get("code");
    const stateParam = req.nextUrl.searchParams.get("state");

    if (!code || !stateParam) {
      return NextResponse.redirect(
        new URL("/settings/integrations?error=missing_code", req.url)
      );
    }

    let state: { orgId: string; integrationId: string };
    try {
      state = JSON.parse(Buffer.from(stateParam, "base64url").toString());
    } catch {
      return NextResponse.redirect(
        new URL("/settings/integrations?error=invalid_state", req.url)
      );
    }

    const clientId = process.env[oauthConfig.clientIdEnv] || "";
    const clientSecret = process.env[oauthConfig.clientSecretEnv] || "";
    const baseUrl = new URL(req.url).origin;
    const redirectUri = `${baseUrl}/api/integrations/oauth/${provider}/callback`;

    const tokenRes = await fetch(oauthConfig.tokenUrl, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        grant_type: "authorization_code",
        code,
        redirect_uri: redirectUri,
        client_id: clientId,
        client_secret: clientSecret,
      }),
    });

    if (!tokenRes.ok) {
      const text = await tokenRes.text().catch(() => "");
      console.error("[oauth/callback] Token exchange failed:", text);
      return NextResponse.redirect(
        new URL("/settings/integrations?error=token_exchange_failed", req.url)
      );
    }

    const tokens = await tokenRes.json();

    if (state.integrationId) {
      const integration = await prisma.integration.findFirst({
        where: {
          id: state.integrationId,
          organizationId: state.orgId,
        },
      });

      if (integration) {
        const existingConfig =
          (integration.config as Record<string, unknown>) || {};
        await prisma.integration.update({
          where: { id: integration.id },
          data: {
            config: {
              ...existingConfig,
              accessToken: tokens.access_token,
              refreshToken: tokens.refresh_token || existingConfig.refreshToken,
              tokenExpiresAt: tokens.expires_in
                ? Date.now() + tokens.expires_in * 1000
                : undefined,
            },
            enabled: true,
            lastSyncStatus: "connected",
            lastSyncAt: new Date(),
          },
        });
      }
    }

    return NextResponse.redirect(
      new URL(
        `/settings/integrations${state.integrationId ? `/${state.integrationId}` : ""}?connected=true`,
        req.url
      )
    );
  } catch (error) {
    console.error("[oauth/callback] error:", error);
    return NextResponse.redirect(
      new URL("/settings/integrations?error=callback_failed", req.url)
    );
  }
}
