import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", }; serve(async (req: Request): Promise => { if (req.method === "OPTIONS") { return new Response(null, { headers: corsHeaders }); } try { const authHeader = req.headers.get("Authorization"); if (!authHeader) { return new Response( JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const supabase = createClient( Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!, { auth: { autoRefreshToken: false, persistSession: false, }, }, ); const token = authHeader.replace("Bearer ", ""); const { data: authData } = await supabase.auth.getUser(token); const user = authData.user; if (!user) { return new Response( JSON.stringify({ error: "Unauthorized" }), { status: 401, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const { amount, notes } = await req.json(); const parsedAmount = Number(amount || 0); if (parsedAmount <= 0) { return new Response( JSON.stringify({ error: "Invalid withdrawal amount" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const { data: wallet } = await supabase .rpc("get_collaborator_wallet", { p_user_id: user.id }); const currentBalance = Number(wallet?.[0]?.current_balance || 0); const { data: settings } = await supabase.rpc("get_collaboration_settings"); const minWithdrawal = Number(settings?.[0]?.min_withdrawal_amount || 100000); const maxPendingWithdrawals = Number(settings?.[0]?.max_pending_withdrawals || 1); if (currentBalance < minWithdrawal) { return new Response( JSON.stringify({ error: `Minimum withdrawal is Rp ${minWithdrawal.toLocaleString("id-ID")}` }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } if (parsedAmount > currentBalance) { return new Response( JSON.stringify({ error: "Insufficient available balance", available: currentBalance }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const { data: existingPending } = await supabase .from("withdrawals") .select("id") .eq("user_id", user.id) .eq("status", "pending"); if ((existingPending?.length || 0) >= maxPendingWithdrawals) { return new Response( JSON.stringify({ error: `Maximum ${maxPendingWithdrawals} pending withdrawal(s) allowed` }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const { data: profile } = await supabase .from("profiles") .select("bank_account_name, bank_account_number, bank_name") .eq("id", user.id) .maybeSingle(); if (!profile?.bank_account_number || !profile?.bank_account_name || !profile?.bank_name) { return new Response( JSON.stringify({ error: "Please complete your bank account information in profile settings" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } const { data: withdrawal, error: createError } = await supabase .from("withdrawals") .insert({ user_id: user.id, amount: parsedAmount, status: "pending", payment_method: "bank_transfer", payment_reference: `${profile.bank_name} - ${profile.bank_account_number} (${profile.bank_account_name})`, notes: notes || null, created_by: user.id, }) .select() .single(); if (createError || !withdrawal) { throw createError || new Error("Failed to create withdrawal"); } const { data: txId, error: holdError } = await supabase .rpc("hold_withdrawal_amount", { p_user_id: user.id, p_withdrawal_id: withdrawal.id, p_amount: parsedAmount, }); if (holdError) { await supabase.from("withdrawals").delete().eq("id", withdrawal.id); throw holdError; } await supabase .from("withdrawals") .update({ wallet_transaction_id: txId }) .eq("id", withdrawal.id); await supabase.functions.invoke("send-collaboration-notification", { body: { type: "withdrawal_requested", withdrawalId: withdrawal.id, userId: user.id, amount: parsedAmount, bankInfo: { bankName: profile.bank_name, accountNumber: profile.bank_account_number, accountName: profile.bank_account_name, }, }, }); return new Response( JSON.stringify({ success: true, withdrawal: { ...withdrawal, wallet_transaction_id: txId }, }), { status: 201, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } catch (error: unknown) { const message = error instanceof Error ? error.message : "Failed to create withdrawal"; return new Response( JSON.stringify({ error: message }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }, ); } });