<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Exception;
use App\Models\User;
use App\Models\Booking;
use App\Models\Transaction;
use App\Models\BankDetail;
use App\Models\ConnectAccount;
use App\Models\Card;
use App\Traits\BookingFare;


class StripeController extends Controller
{
    use BookingFare;
    
    public function addBank(Request $request)
    {
          //Validate the Input request 
        $validator =  $request->validate([
            'name' => 'required|string',
            'alias_name' => 'nullable',
            'account_type' => 'nullable',
            'account_number'    => 'required',
            'bank_code'    => 'nullable',
            'branch_code' => 'nullable',
            'step' => 'required',
            'identity_number' => 'nullable',
           ]);
           
         try{
             
             $user = auth()->user();

             $firstName = $user->first_name;
             $lastName = $user->last_name;
             $aliasName = $request->alias_name ?? null;
             $identityNumber = $user->uinfin ?? $request->identity_number ?? null;
             $phoneNumber = $user->country_code.$user->phone;
             $email = $user->email;
             $dob = $user->dob;
             $accountHolderName = $request->name;
             $AccountNumber = $request->account_number;
             $AccountType   = $request->account_type;
             
             $bankCode = $request->bank_code; 
             $branchCode = $request->branch_code; 
             $RoutingNumber = $bankCode . '-' . $branchCode;
             
             $address = [
                 'address' => $user->address,
                 'country' => $user->country,
                 'postal_code' => $user->postal_code,
                 ];
             
            //  if($user->user_type == User::TYPE_DRIVER){
                 
                 $checkAccount = $this->createConnectAccount($firstName,$lastName,$phoneNumber,$email,$dob,$accountHolderName,$AccountNumber,$RoutingNumber,$identityNumber,$address,$aliasName);
                 
                if($checkAccount['success']==1)
                 {
                 $bankData = array(
                    'user_id'         => $user->id,    
                    'account_type'    => $AccountType,
                    'account_holder_name' => $accountHolderName,
                    'account_number' => $AccountNumber,
                    'routing_number' =>  $RoutingNumber,
                    'alias_name'     => $aliasName
                    );
                      $createBank =  BankDetail::create($bankData);
                        if(!empty($createBank)){
                            
                                $ConnectedAccounts = array(
                                'user_id'   =>    $user->id,    
                                'bank_id'   =>    $createBank->id,    
                                'account_id'    =>    $checkAccount['accountID']
                                );
                                 $createaccount = ConnectAccount::create($ConnectedAccounts);
                                 
                                 $user->step = $request->step;
                                 $user->save();
                        }
                    return $this->jsonResponse(true, 200, 'Bank detail added successfully.');
                     
                 }else{
                     return $this->jsonResponse(true, 400, 'Bank detail not added. please try again!');
                 }
              
                 
            //  }else{
            //          return $this->jsonResponse(true, 400, 'User type is not matched.');
            //  }
            //  $isCheck = ConnectedAccount::where('business_id',$request->user()->id)->first();
            
              
              
         }catch(Exception $e){
             return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
       
    }
    
    public function createCheckoutSession()
    {
         try{
             
            $user = auth()->user();
            
            if(!empty($user)){
                $stripeCustomerId = $user->stripe_customer_id;
                if(!is_null($stripeCustomerId)){
                    $customer =  $this->createCustomer(null, null, $stripeCustomerId);
                }else{
                    $fullName = $user->first_name . ' '. $user->last_name;
                    $email = $user->email;
                    
                  // create new customer 
                  $customer =   $this->createCustomer($email, $fullName, $stripeCustomerId);
                  
                  //check response for success
                  if($customer['success'] == 1){
                     $customerId =  $customer['customer_id'];
                     
                     //Update Customer Id In user Table
                     User::where('id',$user->id)->update(['stripe_customer_id' => $customerId]);
                  }
                  
                }
        
                return $this->jsonResponse(true, 200, 'Checkout session created Successfully.', $customer);
        
            }else{
                 return $this->jsonResponse(true, 400, 'User not found.');
            }
        }catch(Exception $e){
            return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
    }
    
    public function getCardDetail()
    {
        $user = auth()->user();
        
        if(!$user){
           return $this->jsonResponse(true, 200, 'User not found.');
        }
        
       $stripeCustomerId = $user->stripe_customer_id;

        if (!empty($user) && !is_null($stripeCustomerId)) {
            // Retrieve cards from Stripe
            $cards = $this->getCardLists($stripeCustomerId);
            $existingCards = Card::where('user_id', $user->id)->get();
        
            // Create a map of existing card details for comparison
            $existingCardMap = $existingCards->keyBy('stripe_payment_method_id');
        
            foreach ($cards['cardData'] as $data) {
                $stripeCardId = $data->id;
                $cardDetails = [
                    'user_id' => $user->id,
                    'stripe_payment_method_id' => $stripeCardId,
                    'card_brand' => $data->card->brand,
                    'card_holder_name' => $data->billing_details->name,
                    'last4' => $data->card->last4,
                    'expiry_month' => $data->card->exp_month,
                    'expiry_year' => $data->card->exp_year,
                    'status' => 1,
                ];
        
                if (isset($existingCardMap[$stripeCardId])) {
                    // Check if any details have changed
                    $existingCard = $existingCardMap[$stripeCardId];
                    if (
                        $existingCard->card_brand !== $data->card->brand ||
                        $existingCard->card_holder_name !== $data->billing_details->name ||
                        $existingCard->last4 !== $data->card->last4 ||
                        $existingCard->expiry_month !== $data->card->exp_month ||
                        $existingCard->expiry_year !== $data->card->exp_year
                    ) {
                        // Update existing card if details differ
                        $existingCard->update($cardDetails);
                    }
                } else {
                    // Insert new card if it doesn't exist in the database
                    Card::create($cardDetails);
                }
            }
        
            // Return the updated list of cards from the database
            $cardsData = Card::where('user_id', $user->id)->get();

            return $this->jsonResponse(true, 200, 'Card list fetched.', $cardsData);
            
        }else{
             return $this->jsonResponse(true, 200, 'User not found or customer not created.',[]);
        }
        
    }
    
    // charge the payment created by payment intent or using gpay apple pay token 
    public function charge(Request $request)
    {
         try{
                  //Validate the Input request 
                $validator =  $request->validate([
                    'booking_id' => 'required',
                    'card_id' => 'required|string',
                    'amount' => 'required',
                    'payment_type' => 'required',
                    'payment_method' => 'required',
                    'payment_description' => 'nullable',
                   ]);
                   
                $user = auth()->user();
                //get the fare rates
                $fares = $this->fares();
                
                //get the payment method to know its a card, apple pay or google pay
                $paymentMethod = $request->payment_method;
                
                $stripeCustomerId = $user->stripe_customer_id;
                
                //create customer id in case its not card 
                if(!is_null($stripeCustomerId)){
                    $customer =  $this->createCustomer(null, null, $stripeCustomerId);
                }else{
                    $fullName = $user->first_name . ' '. $user->last_name;
                    $email = $user->email;
                    
                  // create new customer 
                  $customer =   $this->createCustomer($email, $fullName, $stripeCustomerId);
                  
                  //check response for success
                  if($customer['success'] == 1){
                     $stripeCustomerId =  $customer['customer_id'];
                     
                     //Update Customer Id In user Table
                     User::where('id',$user->id)->update(['stripe_customer_id' => $stripeCustomerId]);
                  }
                  
                }
                
                $amount = $request->amount;
                $bookingId = $request->booking_id;
                $firstName =  $user->first_name ? $user->first_name : null;
                $lastName = $user->last_name ? $user->last_name : null;
                $email = $user->email ? $user->email : null;
                $name = $firstName . ''. $lastName;
                $phone =  $user->phone ? $user->phone : null;
                
                if($paymentMethod != 'card'){
                    //get the gpay / apple pay token using card_id 
                    $paymentmethodPayload = [
                        'token' => $request->card_id,
                        'name' => $name,
                        'email'  => $email,
                        'phone' => $phone,
                        'booking_id' => $bookingId,
                        ];
                        
                    $paymentMethodResponse = $this->createPaymentMethod($paymentmethodPayload);
                    
                    $cardId = $paymentMethodResponse['paymentMethodId'];
                    
                }else{
                    $cardId = $request->card_id;   
                     //get card detail used in payment 
                    $CardDetail = Card::where('user_id', $user->id)->where('stripe_payment_method_id',$cardId)->first();
                }
                $paymentType = $request->payment_type;
                 
                $booking = Booking::where('booking_id',$bookingId)->first();
                
                
                $chargeDetail = [
                    'first_name' => $firstName,
                    'last_name' => $lastName,
                    'email'    => $email, 
                    'phone'   => $phone, 
                    'bookingID' => $bookingId,
                    'description' => $request->payment_description ? $request->payment_description : null ,
                    ];
                
                $charge = $this->createPaymentIntent($amount,$stripeCustomerId,$cardId,$paymentType,$chargeDetail);
                if($charge['success'] == 1){
                    
                   $paymentId =  $charge['paymentIntent']->id;
                    if(!empty($paymentId)){
                        
                        // Booking::where('booking_id',$bookingId)->update(['payment_id' => $paymentId,'is_paid' => 1]);    
                        
                       
                        
                       $platfromFee = 0;
                        if($paymentType == 'booking_fee'){
                            
                              Booking::where('booking_id',$bookingId)->update(['payment_id' => $paymentId,'is_paid' => 1]);   
                             $status = Transaction::STATUS_ON_HOLD;
                             //booking platform fee with including the additional stop platform fee
                             $platfromFee = $booking->platform_fee;
                        }else{
                            if($paymentType == 'delay_fee'){
                                $platfromFee = $fares['rider_delay_fee_cut'];
                            }
                             $status = Transaction::STATUS_SUCCEEDED;
                        }
                        
                       
                    //   if($paymentMethod == 'card'){
                    //           //Save the payment detail in db for future reference  
                    //   $transaction =  Transaction::create([
                    //         'user_id' => $user->id,
                    //         'booking_id' => $booking->id,
                    //         'card_id' => $CardDetail->id,
                    //         'transaction_id' => $paymentId,
                    //         'holder_name'   => $CardDetail->card_holder_name,
                    //         'expiry_month' => $CardDetail->expiry_month,
                    //         'expiry_year' => $CardDetail->expiry_year,
                    //         'last_digits' => $CardDetail->last4,
                    //         'amount' => $amount,
                    //         'platform_fee' => $platfromFee,
                    //         'status' => $status,
                    //         'purpose' => $request->payment_type,
                    //         'payment_method' => $paymentMethod,
                    //         ]);
                    //   }else{
                    //             //Save the payment detail in db for future reference  
                    //       $transaction =  Transaction::create([
                    //             'user_id' => $user->id,
                    //             'booking_id' => $booking->id,
                    //             'card_id' => $cardId,
                    //             'transaction_id' => $paymentId,
                    //             'holder_name'   => $name,
                    //             'amount' => $amount,
                    //             'platform_fee' => $platfromFee,
                    //             'status' => $status,
                    //             'purpose' => $request->payment_type,
                    //             'payment_method' => $paymentMethod,
                    //             ]);
                    //   }
                    
                    $transactionData = [
                        'user_id' => $user->id,
                        'booking_id' => $booking->id,
                        'transaction_id' => $paymentId,
                        'amount' => $amount,
                        'platform_fee' => $platfromFee,
                        'status' => $status,
                        'purpose' => $request->payment_type,
                        'payment_method' => $paymentMethod,
                    ];
                    
                    // Add card details if payment method is 'card'
                    if ($paymentMethod == 'card') {
                        $transactionData['card_id'] = $CardDetail->id;
                        $transactionData['holder_name'] = $CardDetail->card_holder_name;
                        $transactionData['expiry_month'] = $CardDetail->expiry_month;
                        $transactionData['expiry_year'] = $CardDetail->expiry_year;
                        $transactionData['last_digits'] = $CardDetail->last4;
                    } else {
                        $transactionData['card_id'] = $cardId;
                        $transactionData['holder_name'] = $name;
                    }
                    
                    // Save the transaction
                    $transaction = Transaction::create($transactionData);
                    
                    }
                    
                    return $this->jsonResponse(true, 200, 'Payment Successful.');
                }else{
                    \Log::info($charge);
                    return $this->jsonResponse(true, 400, 'Payment Failed.');  
                }
                
         }catch(Exception $e){
             return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
    }
    
    
    public function confirmPayment(Request $request)
    {
         try{
                  //Validate the Input request 
                $validator =  $request->validate([
                    'booking_id' => 'required',
                    'updated_amount' => 'nullable',
                    'update_amount_reason' => 'nullable',
                   ]);
               
              $bookingId = $request->booking_id;
              
              //get the fare rates
              $fares = $this->fares();
               
             $booking = Booking::with(['transactions', 'cards'])->where('booking_id', $bookingId)->first();
             $driverId = $booking->driver_id;

            if (!$booking) {
                return $this->jsonResponse(false, 400, 'Booking not found.');
            }
            
             
            
            // Check if booking is completed and payment is on hold
            if ($booking->is_paid == Booking::PAYMENT_ON_HOLD) {
                // Get the first transaction where payment_id matches transaction_id and purpose is 'booking_fee'
                $transaction = $booking->transactions->first(function ($transaction) use ($booking) {
                    return $transaction->transaction_id == $booking->payment_id && $transaction->purpose == 'booking_fee';
                });
            
                if (!$transaction) {
                    return $this->jsonResponse(false, 400, 'No matching transaction found for booking fee.');
                }
            
                // Get the card_id from the matching transaction
                $cardId = $transaction->card_id;
                $card = $booking->cards->firstWhere('id', $cardId);
            
                if (!$card) {
                    return $this->jsonResponse(false, 400, 'No matching card found for the transaction.');
                }
                $transactionData = [];
                //checks the amount is not null and having key updated amount 
                if ($request->filled('updated_amount')) {
                   
                   $updatedAmount =  $this->updatePaymentIntent([
                       'paymentIntentId'=> $transaction->transaction_id, 
                       'updated_amount' => $request->updated_amount ,
                       'update_amount_reason' => $request->update_amount_reason ? $request->update_amount_reason : "extra charges"
                   ]);
                
                    // dd($updatedAmount);
                    if(!$updatedAmount['success'] == 1){
                         return $this->jsonResponse(true, 400, 'Unable to update the amount.'); 
                    }
                    $transactionData['amount'] = $request->updated_amount;
                }
                
                // Prepare the payload for payment confirmation
                $confirmationPayload = [
                    'paymentIntentId' => $transaction->transaction_id,
                    'card_id' => $card->stripe_payment_method_id,
                ];
                
              
            
                // Confirm the payment
                $paymentConfirm = $this->Confirmcharge($confirmationPayload);
            
                if (!isset($paymentConfirm['success']) || $paymentConfirm['success'] != 1) {
                    return $this->jsonResponse(false, 400, 'Payment confirmation failed. Please contact support for assistance.', $paymentConfirm);
                }
            
                // Update booking and transaction records upon successful payment confirmation
                $booking->update(['is_paid' => Booking::PAYMENT_PAID]);
                $transactionData['status'] = Transaction::STATUS_SUCCEEDED;
                $transaction->update($transactionData);
                
                
                
                // transfer amount if driver available 
                if(!is_null($driverId)){
                     
                     $driverEarning = 0;
                     
                    $connectAccount = ConnectAccount::where('user_id',$driverId)->first();
                    $connectAccountId = $connectAccount->id;
               
                    //check if rider cancels the ride and booking is accepted to get the earning of  
                    if($booking->canceled_by == 1 && $booking->status == Booking::STATUS_ACCEPTED){
                         $driverEarning = $booking->rider_cancelation_fee - $booking->rider_cancelation_platform_fee;
                    }else{
                        $driverEarning = $booking->driver_fee;
                    }
                   
                    //check delay and late fee to pay driver
                    if($booking->is_delayed == 1 && $booking->rider_delayed_fee > 0){
                        //get the delay earning with substract platform fee 
                        $platformDelayCharges = $booking->rider_delayed_count *  $fares['rider_delay_fee_cut'];
                        $driverEarning =+ $booking->rider_delayed_fee - $platformDelayCharges;
                    }
                    
                    $driverDetail = [
                        'amount' => $driverEarning, 
                        'connect_account' => $connectAccountId,
                        ];
                    
                    //transfer driver earnings to driver
                  $fundTransferResponse =   $this->fundTransfer($driverDetail);
                  if($fundTransferResponse['success'] == 1){
                      
                        $bankTransferResponse =   $this->createStripePayout($connectAccountId,$driverEarning);
                        if($bankTransferResponse['success'] == 1){
                             $payoutId = $bankTransferResponse['payout']->id;
                             $transactionData = [
                                'user_id' => $driverId,
                                'booking_id' => $booking->id,
                                'transaction_id' => $payoutId,
                                'amount' => $driverEarning,
                                'platform_fee' => 0 ,
                                'status' => Transaction::STATUS_SUCCEEDED,
                                'purpose' => 'driver_earning',
                                'payment_method' => 'transfer',
                            ];
                            
                            Transaction::create($transactionData);
                        }
                      
                  }else{
                      \Log::info("Error in fund Transfer to driver:",$fundTransferResponse['message']);
                  }
                }
               
                
            
                return $this->jsonResponse(true, 200, 'Payment confirmed and Ride completed successfully.');
            }
            else{
                    return $this->jsonResponse(true, 400, 'Payment Confirmation Failed.');  
               }
               
               
         }catch(Exception $e){
             return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
    }
    
    
    public function refundPayment(Request $request)
    {
         try{
              
              
         }catch(Exception $e){
             return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
    }
    
    public function testPayment(Request $request)
    {
         try{
            //  dd($request);
             $token = $request->token;
             $response =  $this->retrivePayment($token);
              dd($response);
              
         }catch(Exception $e){
             return $this->jsonResponse(false, 500, 'An error occurred.', null, 500, ["message" => $e->getMessage()]);
        }
    }
    
    
    
    //for directly making payment from card
    public function makePayment(Request $request)
    {
        
         //Validate the Input request 
        $validator =  $request->validate([
            'booking_id' => 'required',
            'amount' => 'required',
           ]);
           
        $user = auth()->user();
           
        $bookingID = $request->booking_id;
        
        $amount = $request->amount;
        
        $productId =  $this->createProduct($bookingID);
        
        $priceId =  $this->createPrice($amount,$productId);
        
        if($priceId){
            
             $session =  $this->createSession($priceId);
        }
        
        
        // dd("here");
        
    }
    
    
    
}
