import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.49.1";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type",
};

interface PayPalConfig {
  client_id: string;
  client_secret: string;
  webhook_id?: string;
}

// Helper to log webhook events to the database
async function logWebhookEvent(
  supabase: any,
  gateway: string,
  eventType: string,
  eventId: string | null,
  status: string,
  payload: any,
  responseStatus: number,
  errorMessage: string | null,
  startTime: number
) {
  try {
    await supabase.from("webhook_event_logs").insert({
      gateway,
      event_type: eventType,
      event_id: eventId,
      status,
      payload: typeof payload === "string" ? JSON.parse(payload) : payload,
      response_status: responseStatus,
      error_message: errorMessage,
      processing_time_ms: Date.now() - startTime,
    });
  } catch (err) {
    console.error("Failed to log webhook event:", err);
  }
}

async function getPayPalConfig(supabase: any): Promise<{ config: PayPalConfig; isTestMode: boolean } | null> {
  const { data, error } = await supabase
    .from("payment_gateway_configs")
    .select("*")
    .eq("gateway", "paypal")
    .single();

  if (error || !data) {
    return null;
  }

  const configData = data.is_test_mode ? data.sandbox_config : data.live_config;
  
  return {
    config: configData as PayPalConfig,
    isTestMode: data.is_test_mode,
  };
}

async function verifyWebhookSignature(
  config: PayPalConfig,
  isTestMode: boolean,
  headers: Headers,
  body: string
): Promise<boolean> {
  if (!config.webhook_id) {
    console.warn("No webhook ID configured, skipping verification");
    return true; // Allow in dev/sandbox mode without strict verification
  }

  const baseUrl = isTestMode
    ? "https://api-m.sandbox.paypal.com"
    : "https://api-m.paypal.com";

  const auth = btoa(`${config.client_id}:${config.client_secret}`);

  // Get access token
  const tokenResponse = await fetch(`${baseUrl}/v1/oauth2/token`, {
    method: "POST",
    headers: {
      Authorization: `Basic ${auth}`,
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: "grant_type=client_credentials",
  });

  if (!tokenResponse.ok) {
    return false;
  }

  const tokenData = await tokenResponse.json();

  // Verify webhook signature
  const verifyResponse = await fetch(
    `${baseUrl}/v1/notifications/verify-webhook-signature`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${tokenData.access_token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        auth_algo: headers.get("paypal-auth-algo"),
        cert_url: headers.get("paypal-cert-url"),
        transmission_id: headers.get("paypal-transmission-id"),
        transmission_sig: headers.get("paypal-transmission-sig"),
        transmission_time: headers.get("paypal-transmission-time"),
        webhook_id: config.webhook_id,
        webhook_event: JSON.parse(body),
      }),
    }
  );

  if (!verifyResponse.ok) {
    return false;
  }

  const verifyData = await verifyResponse.json();
  return verifyData.verification_status === "SUCCESS";
}

async function capturePayPalOrder(
  config: PayPalConfig,
  isTestMode: boolean,
  orderId: string
): Promise<any> {
  const baseUrl = isTestMode
    ? "https://api-m.sandbox.paypal.com"
    : "https://api-m.paypal.com";

  const auth = btoa(`${config.client_id}:${config.client_secret}`);

  const tokenResponse = await fetch(`${baseUrl}/v1/oauth2/token`, {
    method: "POST",
    headers: {
      Authorization: `Basic ${auth}`,
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: "grant_type=client_credentials",
  });

  const tokenData = await tokenResponse.json();

  const captureResponse = await fetch(
    `${baseUrl}/v2/checkout/orders/${orderId}/capture`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${tokenData.access_token}`,
        "Content-Type": "application/json",
      },
    }
  );

  return captureResponse.json();
}

serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response(null, { headers: corsHeaders });
  }

  const startTime = Date.now();
  let eventType = "unknown";
  let eventId: string | null = null;

  try {
    const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
    const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
    const supabase = createClient(supabaseUrl, supabaseServiceKey);

    const body = await req.text();
    const event = JSON.parse(body);

    eventType = event.event_type || "unknown";
    eventId = event.id || null;
    console.log("PayPal webhook event:", eventType);

    // Get PayPal config
    const paypalResult = await getPayPalConfig(supabase);
    if (!paypalResult) {
      console.error("PayPal not configured");
      await logWebhookEvent(supabase, "paypal", eventType, eventId, "failed", { type: eventType }, 200, "PayPal not configured", startTime);
      return new Response("OK", { status: 200 });
    }

    const { config, isTestMode } = paypalResult;

    // Verify webhook signature (optional in sandbox)
    const isValid = await verifyWebhookSignature(config, isTestMode, req.headers, body);
    if (!isValid && !isTestMode) {
      console.error("Invalid webhook signature");
      await logWebhookEvent(supabase, "paypal", eventType, eventId, "failed", { type: eventType }, 401, "Invalid webhook signature", startTime);
      return new Response("Invalid signature", { status: 401 });
    }

    const resource = event.resource;

    switch (eventType) {
      case "CHECKOUT.ORDER.APPROVED": {
        // User approved the payment, now capture it
        const orderId = resource.id;
        
        const captureResult = await capturePayPalOrder(config, isTestMode, orderId);
        console.log("Capture result:", captureResult);

        if (captureResult.status === "COMPLETED") {
          // Update transaction as completed
          const { data: transaction } = await supabase
            .from("payment_transactions")
            .select("*")
            .eq("paypal_order_id", orderId)
            .single();

          if (transaction) {
            await supabase
              .from("payment_transactions")
              .update({
                status: "completed",
                external_transaction_id: captureResult.id,
              })
              .eq("id", transaction.id);

            // Process based on transaction type
            if (transaction.transaction_type === "credit_purchase" && transaction.reference_id) {
              // Get credit pack and add credits
              const { data: pack } = await supabase
                .from("credit_packs")
                .select("credits")
                .eq("id", transaction.reference_id)
                .single();

              if (pack) {
                await supabase.rpc("add_credits", {
                  p_user_id: transaction.user_id,
                  p_amount: pack.credits,
                  p_credit_type: "bonus",
                  p_action_type: "paypal_purchase",
                  p_description: `Purchased credit pack via PayPal`,
                });
              }
            } else if (transaction.transaction_type === "subscription" && transaction.reference_id) {
              // Handle subscription activation
              const { data: plan } = await supabase
                .from("subscription_plans")
                .select("*")
                .eq("id", transaction.reference_id)
                .single();

              if (plan) {
                const billingCycle = (transaction.metadata as any)?.billing_cycle || "monthly";
                const periodEnd = new Date();
                periodEnd.setMonth(periodEnd.getMonth() + (billingCycle === "yearly" ? 12 : 1));

                await supabase.from("user_subscriptions").upsert(
                  {
                    user_id: transaction.user_id,
                    plan_id: plan.id,
                    status: "active",
                    billing_cycle: billingCycle,
                    payment_method: "paypal",
                    current_period_start: new Date().toISOString(),
                    current_period_end: periodEnd.toISOString(),
                  },
                  { onConflict: "user_id" }
                );

                // Add monthly credits
                await supabase.rpc("add_credits", {
                  p_user_id: transaction.user_id,
                  p_amount: plan.monthly_credits,
                  p_credit_type: "monthly",
                  p_action_type: "subscription_renewal",
                  p_description: `${plan.name} subscription via PayPal`,
                });
              }
            } else if (transaction.transaction_type === "invoice_payment" && transaction.reference_id) {
              // Mark invoice as paid
              await supabase
                .from("invoices")
                .update({
                  status: "paid",
                  paid_at: new Date().toISOString(),
                })
                .eq("id", transaction.reference_id);
            }
          }
        }
        break;
      }

      case "PAYMENT.CAPTURE.COMPLETED": {
        // Payment captured successfully - handled above in CHECKOUT.ORDER.APPROVED
        console.log("Payment capture completed:", resource.id);
        break;
      }

      case "PAYMENT.CAPTURE.DENIED":
      case "PAYMENT.CAPTURE.REFUNDED": {
        // Handle failed/refunded payments
        const orderId = resource.supplementary_data?.related_ids?.order_id;
        if (orderId) {
          await supabase
            .from("payment_transactions")
            .update({
              status: eventType === "PAYMENT.CAPTURE.REFUNDED" ? "refunded" : "failed",
            })
            .eq("paypal_order_id", orderId);
        }
        break;
      }

      case "BILLING.SUBSCRIPTION.ACTIVATED": {
        // Subscription activated
        const subscriptionId = resource.id;
        
        // Get the transaction to find plan details
        const { data: transaction } = await supabase
          .from("payment_transactions")
          .select("*")
          .eq("paypal_subscription_id", subscriptionId)
          .single();

        if (transaction) {
          await supabase
            .from("payment_transactions")
            .update({ 
              status: "completed",
              external_transaction_id: subscriptionId,
            })
            .eq("id", transaction.id);

          // Get plan and activate subscription
          const { data: plan } = await supabase
            .from("subscription_plans")
            .select("*")
            .eq("id", transaction.reference_id)
            .single();

          if (plan) {
            const billingCycle = (transaction.metadata as any)?.billing_cycle || "monthly";
            const periodEnd = new Date();
            periodEnd.setMonth(periodEnd.getMonth() + (billingCycle === "yearly" ? 12 : 1));

            await supabase.from("user_subscriptions").upsert(
              {
                user_id: transaction.user_id,
                plan_id: plan.id,
                status: "active",
                billing_cycle: billingCycle,
                payment_method: "paypal",
                external_subscription_id: subscriptionId,
                current_period_start: new Date().toISOString(),
                current_period_end: periodEnd.toISOString(),
              },
              { onConflict: "user_id" }
            );

            // Add monthly credits
            await supabase.rpc("add_credits", {
              p_user_id: transaction.user_id,
              p_amount: plan.monthly_credits,
              p_credit_type: "monthly",
              p_action_type: "subscription_activation",
              p_description: `${plan.name} subscription activated via PayPal`,
            });
          }
        }
        break;
      }

      case "BILLING.SUBSCRIPTION.PAYMENT.COMPLETED": {
        // Recurring payment completed
        const subscriptionId = resource.id || resource.billing_agreement_id;
        
        const { data: subscription } = await supabase
          .from("user_subscriptions")
          .select("*, subscription_plans(*)")
          .eq("external_subscription_id", subscriptionId)
          .eq("payment_method", "paypal")
          .single();

        if (subscription) {
          const plan = subscription.subscription_plans;
          const billingCycle = subscription.billing_cycle;
          const periodEnd = new Date();
          periodEnd.setMonth(periodEnd.getMonth() + (billingCycle === "yearly" ? 12 : 1));

          // Update subscription period
          await supabase
            .from("user_subscriptions")
            .update({
              current_period_start: new Date().toISOString(),
              current_period_end: periodEnd.toISOString(),
              status: "active",
            })
            .eq("id", subscription.id);

          // Add monthly credits
          await supabase.rpc("add_credits", {
            p_user_id: subscription.user_id,
            p_amount: plan.monthly_credits,
            p_credit_type: "monthly",
            p_action_type: "subscription_renewal",
            p_description: `${plan.name} subscription renewed via PayPal`,
          });

          // Record transaction
          await supabase.from("payment_transactions").insert({
            user_id: subscription.user_id,
            amount: billingCycle === "yearly" ? plan.price_yearly : plan.price_monthly,
            currency: "USD",
            payment_method: "paypal",
            transaction_type: "subscription_renewal",
            status: "completed",
            paypal_subscription_id: subscriptionId,
            reference_id: plan.id,
            metadata: {
              billing_cycle: billingCycle,
              is_recurring: true,
            },
          });
        }
        break;
      }

      case "BILLING.SUBSCRIPTION.CANCELLED":
      case "BILLING.SUBSCRIPTION.EXPIRED":
      case "BILLING.SUBSCRIPTION.SUSPENDED": {
        // Handle subscription cancellation/expiry/suspension
        const subscriptionId = resource.id;
        
        const status = eventType === "BILLING.SUBSCRIPTION.SUSPENDED" ? "past_due" : "cancelled";
        
        await supabase
          .from("user_subscriptions")
          .update({ 
            status,
            cancel_at_period_end: eventType !== "BILLING.SUBSCRIPTION.SUSPENDED",
          })
          .eq("external_subscription_id", subscriptionId)
          .eq("payment_method", "paypal");
        break;
      }

      case "BILLING.SUBSCRIPTION.PAYMENT.FAILED": {
        // Payment failed - mark subscription as past due
        const subscriptionId = resource.id || resource.billing_agreement_id;
        
        await supabase
          .from("user_subscriptions")
          .update({ status: "past_due" })
          .eq("external_subscription_id", subscriptionId)
          .eq("payment_method", "paypal");
        break;
      }

      default:
        console.log("Unhandled event type:", eventType);
    }

    // Log successful processing
    await logWebhookEvent(supabase, "paypal", eventType, eventId, "processed", { type: eventType, id: eventId }, 200, null, startTime);

    return new Response("OK", { status: 200, headers: corsHeaders });
  } catch (error) {
    console.error("PayPal webhook error:", error);
    const message = error instanceof Error ? error.message : "Unknown error";

    // Log failed processing
    await logWebhookEvent(supabase, "paypal", eventType, eventId, "failed", { type: eventType, id: eventId }, 500, message, startTime);

    return new Response("Internal Server Error", { status: 500 });
  }
});
