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;
}

interface CreatePlanRequest {
  action: "create_product" | "create_plan" | "sync_plan" | "list_plans" | "deactivate_plan";
  plan_id?: string;
  billing_cycle?: "monthly" | "yearly";
}

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 || !data.is_enabled) {
    return null;
  }

  const configData = data.is_test_mode ? data.sandbox_config : data.live_config;

  if (!configData?.client_id || !configData?.client_secret) {
    return null;
  }

  return {
    config: configData as PayPalConfig,
    isTestMode: data.is_test_mode,
  };
}

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

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

  const response = 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 (!response.ok) {
    const error = await response.text();
    throw new Error(`PayPal auth failed: ${error}`);
  }

  const data = await response.json();
  return data.access_token;
}

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

  const response = await fetch(`${baseUrl}/v1/catalogs/products`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
      "PayPal-Request-Id": `product-${plan.id}-${Date.now()}`,
    },
    body: JSON.stringify({
      name: plan.name,
      description: plan.description || `${plan.name} subscription plan`,
      type: "SERVICE",
      category: "SOFTWARE",
    }),
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`Failed to create product: ${error}`);
  }

  const data = await response.json();
  return data.id;
}

async function createBillingPlan(
  accessToken: string,
  isTestMode: boolean,
  productId: string,
  plan: any,
  billingCycle: "monthly" | "yearly"
): Promise<string> {
  const baseUrl = isTestMode
    ? "https://api-m.sandbox.paypal.com"
    : "https://api-m.paypal.com";

  const price = billingCycle === "yearly" ? plan.price_yearly : plan.price_monthly;
  const intervalUnit = billingCycle === "yearly" ? "YEAR" : "MONTH";

  const response = await fetch(`${baseUrl}/v1/billing/plans`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
      "PayPal-Request-Id": `plan-${plan.id}-${billingCycle}-${Date.now()}`,
    },
    body: JSON.stringify({
      product_id: productId,
      name: `${plan.name} - ${billingCycle === "yearly" ? "Yearly" : "Monthly"}`,
      description: plan.description || `${plan.name} subscription`,
      status: "ACTIVE",
      billing_cycles: [
        {
          frequency: {
            interval_unit: intervalUnit,
            interval_count: 1,
          },
          tenure_type: "REGULAR",
          sequence: 1,
          total_cycles: 0, // Infinite
          pricing_scheme: {
            fixed_price: {
              value: price.toFixed(2),
              currency_code: "USD",
            },
          },
        },
      ],
      payment_preferences: {
        auto_bill_outstanding: true,
        setup_fee: {
          value: "0",
          currency_code: "USD",
        },
        setup_fee_failure_action: "CONTINUE",
        payment_failure_threshold: 3,
      },
    }),
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`Failed to create billing plan: ${error}`);
  }

  const data = await response.json();
  return data.id;
}

async function deactivatePlan(
  accessToken: string,
  isTestMode: boolean,
  paypalPlanId: string
): Promise<void> {
  const baseUrl = isTestMode
    ? "https://api-m.sandbox.paypal.com"
    : "https://api-m.paypal.com";

  const response = await fetch(`${baseUrl}/v1/billing/plans/${paypalPlanId}/deactivate`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
  });

  if (!response.ok && response.status !== 204) {
    const error = await response.text();
    throw new Error(`Failed to deactivate plan: ${error}`);
  }
}

async function listPayPalPlans(
  accessToken: string,
  isTestMode: boolean
): Promise<any[]> {
  const baseUrl = isTestMode
    ? "https://api-m.sandbox.paypal.com"
    : "https://api-m.paypal.com";

  const response = await fetch(`${baseUrl}/v1/billing/plans?page_size=20&total_required=true`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`Failed to list plans: ${error}`);
  }

  const data = await response.json();
  return data.plans || [];
}

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

  try {
    const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
    const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
    const supabaseAnonKey = Deno.env.get("SUPABASE_ANON_KEY")!;

    // Verify admin user
    const authHeader = req.headers.get("Authorization");
    if (!authHeader) {
      return new Response(JSON.stringify({ error: "Unauthorized" }), {
        status: 401,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    const supabaseClient = createClient(supabaseUrl, supabaseAnonKey, {
      global: { headers: { Authorization: authHeader } },
    });

    const { data: { user } } = await supabaseClient.auth.getUser();

    if (!user) {
      return new Response(JSON.stringify({ error: "Unauthorized" }), {
        status: 401,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    // Check admin role
    const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey);
    const { data: roleData } = await supabaseAdmin.rpc("has_role", {
      _user_id: user.id,
      _role: "admin",
    });

    if (!roleData) {
      return new Response(JSON.stringify({ error: "Admin access required" }), {
        status: 403,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    // Get PayPal config
    const paypalResult = await getPayPalConfig(supabaseAdmin);
    if (!paypalResult) {
      return new Response(
        JSON.stringify({ error: "PayPal is not configured or enabled" }),
        {
          status: 400,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        }
      );
    }

    const { config, isTestMode } = paypalResult;
    const body: CreatePlanRequest = await req.json();
    const accessToken = await getAccessToken(config, isTestMode);

    if (body.action === "list_plans") {
      const plans = await listPayPalPlans(accessToken, isTestMode);
      return new Response(JSON.stringify({ plans }), {
        status: 200,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    if (body.action === "sync_plan" && body.plan_id) {
      // Get the subscription plan
      const { data: plan, error: planError } = await supabaseAdmin
        .from("subscription_plans")
        .select("*")
        .eq("id", body.plan_id)
        .single();

      if (planError || !plan) {
        throw new Error("Subscription plan not found");
      }

      let productId = plan.paypal_product_id;

      // Create product if not exists
      if (!productId) {
        productId = await createProduct(accessToken, isTestMode, plan);
        await supabaseAdmin
          .from("subscription_plans")
          .update({ paypal_product_id: productId })
          .eq("id", plan.id);
      }

      // Create or update monthly plan
      let monthlyPlanId = plan.paypal_plan_id;
      if (!monthlyPlanId && plan.price_monthly > 0) {
        monthlyPlanId = await createBillingPlan(accessToken, isTestMode, productId, plan, "monthly");
        await supabaseAdmin
          .from("subscription_plans")
          .update({ paypal_plan_id: monthlyPlanId })
          .eq("id", plan.id);
      }

      // Create or update yearly plan
      let yearlyPlanId = plan.paypal_yearly_plan_id;
      if (!yearlyPlanId && plan.price_yearly > 0) {
        yearlyPlanId = await createBillingPlan(accessToken, isTestMode, productId, plan, "yearly");
        await supabaseAdmin
          .from("subscription_plans")
          .update({ paypal_yearly_plan_id: yearlyPlanId })
          .eq("id", plan.id);
      }

      return new Response(
        JSON.stringify({
          success: true,
          productId,
          monthlyPlanId,
          yearlyPlanId,
        }),
        {
          status: 200,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        }
      );
    }

    if (body.action === "deactivate_plan" && body.plan_id) {
      const { data: plan } = await supabaseAdmin
        .from("subscription_plans")
        .select("paypal_plan_id, paypal_yearly_plan_id")
        .eq("id", body.plan_id)
        .single();

      if (plan?.paypal_plan_id) {
        await deactivatePlan(accessToken, isTestMode, plan.paypal_plan_id);
      }
      if (plan?.paypal_yearly_plan_id) {
        await deactivatePlan(accessToken, isTestMode, plan.paypal_yearly_plan_id);
      }

      await supabaseAdmin
        .from("subscription_plans")
        .update({
          paypal_plan_id: null,
          paypal_yearly_plan_id: null,
          paypal_product_id: null,
        })
        .eq("id", body.plan_id);

      return new Response(JSON.stringify({ success: true }), {
        status: 200,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    return new Response(JSON.stringify({ error: "Invalid action" }), {
      status: 400,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  } catch (error) {
    console.error("PayPal billing error:", error);
    const errorMessage = error instanceof Error ? error.message : "Internal server error";
    return new Response(
      JSON.stringify({ error: errorMessage }),
      {
        status: 500,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      }
    );
  }
});
