/**
 * POST /api/integrations/connect
 * Initiates or completes integration connection for a CRM/Calendar provider
 *
 * For OAuth providers (Google, Outlook, Salesforce, HubSpot):
 *   - Returns an authorization URL for the user to complete OAuth flow
 *
 * For API-based providers (Zapier, Make):
 *   - Accepts API key/webhook URL and validates the connection
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { getAuthenticatedEmail } from "@/lib/utils/auth-helpers.util";
import { logger } from "@/lib/logger";
import prisma from "@/lib/db";
import { integrationsAdapter } from "@/lib/adapters/integrations";
import { randomUUID } from "crypto";

export const dynamic = "force-dynamic";

// OAuth configuration for different providers
const OAUTH_CONFIG: Record<
  string,
  {
    authUrl: string;
    scopes: string[];
    clientIdEnv: string;
  }
> = {
  google_calendar: {
    authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
    scopes: [
      "https://www.googleapis.com/auth/calendar.readonly",
      "https://www.googleapis.com/auth/calendar.events",
    ],
    clientIdEnv: "GOOGLE_CLIENT_ID",
  },
  outlook_calendar: {
    authUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
    scopes: [
      "openid",
      "profile",
      "email",
      "User.Read",
      "Calendars.ReadWrite",
      "offline_access",
    ],
    clientIdEnv: "MICROSOFT_CLIENT_ID",
  },
  salesforce: {
    authUrl: "https://login.salesforce.com/services/oauth2/authorize",
    scopes: ["api", "refresh_token"],
    clientIdEnv: "SALESFORCE_CLIENT_ID",
  },
  hubspot: {
    authUrl: "https://app.hubspot.com/oauth/authorize",
    scopes: ["crm.objects.contacts.read", "crm.objects.deals.read"],
    clientIdEnv: "HUBSPOT_CLIENT_ID",
  },
};

const VALID_TYPES = [
  "google_calendar",
  "outlook_calendar",
  "salesforce",
  "hubspot",
  "zapier",
  "make",
];

export async function POST(request: NextRequest) {
  try {
    const userEmail = await getAuthenticatedEmail(request, auth);

    if (!userEmail) {
      logger.warn("Unauthorized connect request");
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const body = await request.json();
    const { type, apiKey, webhookUrl } = body;

    if (!type || !VALID_TYPES.includes(type)) {
      return NextResponse.json(
        { error: "Invalid integration type" },
        { status: 400 },
      );
    }

    // Get user from database
    const user = await prisma.users.findUnique({
      where: { email: userEmail },
      select: { id: true },
    });

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

    // Check if integration already exists
    const existingIntegration = await integrationsAdapter.findUnique({
      where: {
        userId_type: {
          userId: user.id,
          type: type,
        },
      },
    });

    // Handle OAuth-based providers
    if (OAUTH_CONFIG[type]) {
      const config = OAUTH_CONFIG[type];
      const clientId = process.env[config.clientIdEnv];

      if (!clientId) {
        logger.warn(`OAuth not configured for ${type}`, { userEmail });

        // Create pending integration record
        const integrationId = existingIntegration?.id || randomUUID();

        await prisma.integrations.upsert({
          where: {
            userId_type: {
              userId: user.id,
              type: type,
            },
          },
          create: {
            id: integrationId,
            userId: user.id,
            type: type,
            status: "pending_setup",
            config: { note: "OAuth credentials not configured" },
            updatedAt: new Date(),
          },
          update: {
            status: "pending_setup",
            config: { note: "OAuth credentials not configured" },
            updatedAt: new Date(),
          },
        });

        // Return a simulated success for demo purposes
        return NextResponse.json({
          success: true,
          message: `${type} integration is pending setup. OAuth credentials will be configured by the administrator.`,
          status: "pending_setup",
          integrationId,
        });
      }

      // Build OAuth authorization URL
      const redirectUri = `${process.env.NEXTAUTH_URL}/api/integrations/callback`;
      const state = Buffer.from(
        JSON.stringify({ userId: user.id, type }),
      ).toString("base64");

      const authUrl = new URL(config.authUrl);
      authUrl.searchParams.set("client_id", clientId);
      authUrl.searchParams.set("redirect_uri", redirectUri);
      authUrl.searchParams.set("response_type", "code");
      authUrl.searchParams.set("scope", config.scopes.join(" "));
      authUrl.searchParams.set("state", state);
      authUrl.searchParams.set("access_type", "offline");
      authUrl.searchParams.set("prompt", "consent");

      logger.info("OAuth URL generated", { userEmail, type });

      return NextResponse.json({
        success: true,
        authUrl: authUrl.toString(),
        message: "Redirect user to authorization URL",
      });
    }

    // Handle API-based providers (Zapier, Make)
    if (type === "zapier" || type === "make") {
      const integrationId = existingIntegration?.id || randomUUID();

      // For webhook-based integrations, store the webhook URL
      const integrationConfig: Record<string, unknown> = {};

      if (webhookUrl) {
        integrationConfig.webhookUrl = webhookUrl;
      }
      if (apiKey) {
        // In production, encrypt this before storing
        integrationConfig.apiKeyHash = Buffer.from(apiKey).toString("base64");
      }

      // Generate a unique webhook endpoint for this user's integration
      const inboundWebhook = `${process.env.NEXTAUTH_URL}/api/integrations/webhook/${integrationId}`;
      integrationConfig.inboundWebhook = inboundWebhook;

      await prisma.integrations.upsert({
        where: {
          userId_type: {
            userId: user.id,
            type: type,
          },
        },
        create: {
          id: integrationId,
          userId: user.id,
          type: type,
          status: "connected",
          config: integrationConfig,
          updatedAt: new Date(),
        },
        update: {
          status: "connected",
          config: integrationConfig,
          lastError: null,
          updatedAt: new Date(),
        },
      });

      logger.info("API integration connected", { userEmail, type });

      return NextResponse.json({
        success: true,
        message: `${type} integration connected successfully`,
        status: "connected",
        integrationId,
        webhookUrl: inboundWebhook,
      });
    }

    return NextResponse.json(
      { error: "Integration type not supported" },
      { status: 400 },
    );
  } catch (error) {
    logger.error("Connect integration error", {
      error: error instanceof Error ? error.message : "Unknown error",
    });

    return NextResponse.json(
      { error: "Failed to connect integration" },
      { status: 500 },
    );
  }
}
