<?php



namespace App\Controllers;



use Square\SquareClient;
use Square\Api\CatalogApi;
use Square\Model\CreateCatalogObjectRequest;
use Square\Model\CatalogObject;
use Square\Model\CatalogTax;
use Square\Model\Money;
use Square\Model\OrderLineItem;
use Square\Model\CreatePaymentRequest;
use Square\Exceptions\ApiException;
use Square\Api\Orders\CreateOrderRequest;
use Square\Api\OrdersApi;
use Square\Api\PaymentsApi;
use Ramsey\Uuid\Uuid;
use App\Models\Transaction_model;
use App\Models\Member_model;
use App\Models\Dashboard_model;
use App\Models\Common_model;
use App\Models\Member_credits_model;
use App\Models\Packages_and_pricing_model;
use App\Models\Cart_model;
use App\Models\Credits_usage_tracking_model;
use App\Models\Rule_model;
use App\Models\Cart_token_model;
use App\Models\Member_address_model;
use App\Models\Zipcode_model;
use App\Models\Country_model;

class PaymentController extends BaseController
{

   



    public function __construct()
    {
        $this->session = session();
		$this->MemberModel = new Member_model();
		$this->dModel = new Dashboard_model();
		$this->cModel = new Common_model();
		$this->creditsModel = new Member_credits_model();
		$this->PackagesModel = new Packages_and_pricing_model();
		$this->cartModel = new Cart_model();
		$this->CreditsUsageTrackingModel = new Credits_usage_tracking_model();
        $this->TransactionModel = new Transaction_model();
        $this->RuleModel = new Rule_model();
        $this->Cart_token_model = new Cart_token_model();
        $this->MemberAddressModel = new Member_address_model();
        $this->ZipcodeModel = new Zipcode_model();
        $this->CountryModel = new Country_model();

    }

  

    

    public function index($token = null)
    {
        if($this->request->getmethod() == 'post')
		{
        //    echo $token;die();
            if(!session()->has('logged_user'))
		     {
                // $count = $this->request->getVar('count');
                // foreach ($count as $key => $value) 
                // {
                //     $this->Cart_token_model->where('id', $this->request->getVar('cart_token_id')[$key] )->set(array( 'count' => $value ))->update();
                // }

			  $this->session->set('token',$token);
			  return redirect()->to(base_url());
		     }
             else{

                $this->payment_form();
             }


        } else {
            //  echo $this->session->get('logged_user');die();
             $this->payment_form();

        }

    }

       

    







    public function payment_form()
    {
        // if(!session()->has('logged_user'))
        //     {
        //      return redirect()->to(base_url());
        //     }

            $CartData = $this->cartModel->where('member_id',session()->get('logged_user'))->findAll();
            $count = count($CartData);
            if($count)
            {
                $credit_pack_expiry_duration = $this->RuleModel->select('value')->where('rule_key', 1 )->get()->getRow()->value;
                $gst = $this->RuleModel->select('value')->where('rule_key', 3 )->get()->getRow()->value;
                $pst = $this->RuleModel->select('value')->where('rule_key', 4 )->get()->getRow()->value;
                $today = date("Y-m-d");
                $days = "+".$credit_pack_expiry_duration." days";
                $amount = 0;
                $item_count = 0;

                if($CartData[0]['order_id'] == null)
                {
                    $orderId = 'EGF'.rand(10,100).rand(10,100).rand(10,100);
                }else{
                    $orderId = $CartData[0]['order_id'];
                }

                 $packageArray = [];

                 for($i=0;$i<$count;$i++)   
                 {
                    $packageData = $this->PackagesModel->where('id',$CartData[$i]['pack_id'])->find();
                    $packageData[0]['count'] = $CartData[$i]['count'];

                    array_push($packageArray , $packageData[0]);

                    $cost = $packageData[0]['cost'] * $CartData[$i]['count'];
                   

                    $credits_data['member_id'] = session()->get('logged_user');
                    $credits_data['pack_id'] =  $packageData[0]['id'];
                    $credits_data['package_name'] = $packageData[0]['package_name'];
                    $credits_data['package_type'] = $packageData[0]['package_type'];
                    $credits_data['credit_points'] = $packageData[0]['credit'];
                    $credits_data['running_balance'] = $packageData[0]['credit'];
                    $credits_data['expired_points'] = 0;
                    $credits_data['expiring_date'] = date('Y-m-d', strtotime($days, strtotime($today)));
                    $credits_data['cost'] = $packageData[0]['cost'];
                    $credits_data['is_active'] = 0;
                    $credits_data['order_id'] = $orderId;
                    $credits_data['cost_with_tax'] =   ( $packageData[0]['cost'] + (($packageData[0]['cost'] * ($gst + $pst) ) / 100) );
                    

                    $creditsModel_pack_count = $this->creditsModel->selectCount('id')->where('pack_id',$packageData[0]['id'])->where('order_id',$orderId)->where('member_id', session()->get('logged_user'))->get()->getRow()->id;
                    if($creditsModel_pack_count)
                    {
                        $this->creditsModel->where('pack_id',$packageData[0]['id'])->where('order_id',$orderId)->where('member_id', session()->get('logged_user'))
                             ->set(array('cost'=>$packageData[0]['cost'],'cost_with_tax'=>( $packageData[0]['cost'] + (($packageData[0]['cost'] * ($gst + $pst) ) / 100) ),'credit_points'=>$packageData[0]['credit'],'running_balance'=>$packageData[0]['credit'],'package_name'=>$packageData[0]['package_name'],'package_type'=>$packageData[0]['package_type']))->update();
                    }
                    $single_pack_no_of_count = $CartData[$i]['count'] - $creditsModel_pack_count;

                    // if($CartData[0]['order_id'] == null)
                    // {
                      for($j=0;$j<$single_pack_no_of_count;$j++)   
                      {
                          $insert_data = $this->creditsModel->save($credits_data);
                      }

                      $this->cartModel->where('id', $CartData[$i]['id'] )
                             ->where('member_id', session()->get('logged_user'))
                             ->set(array( 'order_id' => $orderId   ))->update();
                    // }
                    $amount = $amount + $cost;
                    $item_count = $item_count + $CartData[$i]['count'];
                 }



                $data['amount'] = $amount;
                $data['item_count'] = $item_count;
                $data['order_id'] = $orderId;
                $data['gst'] = $gst;
                $data['pst'] = $pst;
                $data['packageArray'] = $packageArray;
                $data['EncodedArray'] = json_encode($packageArray);
                $data['country'] = $this->CountryModel->findAll();
                $data['userdata'] = $this->MemberModel->where('id',  session()->get('logged_user'))->find();
    
                $if_trans_exist = $this->TransactionModel->where('member_id', session()->get('logged_user'))
                                                         ->where('order_id', $orderId )->find();
                if($if_trans_exist){ 
                //skip insertion
                 }else{
                //Trancaction Table initial entry for this transaction 
                $TrancactionData['status'] = 'In-Progress';
                $TrancactionData['member_id'] = session()->get('logged_user');
                $TrancactionData['order_id'] =   $orderId;
                $insert = $this->TransactionModel->save($TrancactionData);
                }

                $zip = $this->ZipcodeModel->findAll();
		        $output = '<option value="">'.$data['userdata'][0]['pincode'].'</option>';
		        foreach($zip as $row)
		        {
		        $output .= '<option value="'.$row['id'].'">'.$row['code'].'</option>';
		        }
		        $data['zipcode'] = $output;
            // echo '<pre>';
            // print_r($data);
            // echo '</pre>';
            // die();
                echo view('checkout',$data);  
            } else {  	return redirect()->to(base_url()."view/".md5(session()->get('logged_user')));  }

    }



public function processPayment()
{

        try { 

        if ($_SERVER['REQUEST_METHOD'] != 'POST') { 
            error_log('Received a non-POST request');
            echo 'Request not allowed';
            http_response_code(405);
            return;
        }


        include 'app/Libraries/LocationInfo.php';



        $json = file_get_contents('php://input');
        $data = json_decode($json);
        $gst = $this->RuleModel->select('value')->where('rule_key', 3 )->get()->getRow()->value;
        $pst = $this->RuleModel->select('value')->where('rule_key', 4 )->get()->getRow()->value;
        $token = $data->token;
        $idempotencyKey = $data->idempotencyKey;
        $amount = $data->amount;
        $order_id = $data->order_id;  
        $add = $data->address;
        $EncodedArray = json_decode($data->EncodedArray,true);
        parse_str( $add, $address);

       
       

        $Final_amount =  round( ( $amount + (($amount * ($gst + $pst) ) / 100) ) , 2 );
        $Final_amount = $Final_amount * 100;

        $locationId = getenv('SQUARE_LOCATION_ID');
        
        $square_client = new SquareClient([
            'accessToken' => getenv('SQUARE_ACCESS_TOKEN'),
            'environment' => getenv('ENVIRONMENT'),
            'userAgentDetail' => 'golf_evo', // Remove or replace this detail when building your own app
        ]);


        try {
            //create order for the payment
            // $order_line_item = new \Square\Models\OrderLineItem('1');
            // $order_line_item->setCatalogObjectId('EVYRQAQXPNUJWLLMAAHDXUHI');
            // $order_line_item1 = new \Square\Models\OrderLineItem('2');
            // $order_line_item1->setCatalogObjectId('CMU64OVJDUL7YJAFGQI33IZM');

            // $line_items = [$order_line_item,$order_line_item1];
            $line_items = [];
            foreach ($EncodedArray as $key => $row) 
            {
                $order_line_item = '';
                $order = $order_line_item.$key;
               
                $order = new \Square\Models\OrderLineItem($row['count']);
                $order->setCatalogObjectId($row['variation_id']);
                array_push($line_items , $order);
            }

            $pricing_options = new \Square\Models\OrderPricingOptions();
            $pricing_options->setAutoApplyTaxes(true);
            
            $order = new \Square\Models\Order($locationId);
            $order->setLineItems($line_items);
            $order->setPricingOptions($pricing_options);
            
            $body = new \Square\Models\CreateOrderRequest();
            $body->setOrder($order);
            $body->setIdempotencyKey($idempotencyKey);
           
            $order_api_response = $square_client->getOrdersApi()->createOrder($body);

            if ($order_api_response->isSuccess()) {


            $Data['order'] = json_encode($order_api_response->getResult());
            $this->TransactionModel->where('member_id', session()->get('logged_user'))
                                             ->where('order_id', $order_id )
                                             ->set($Data)->update();

            $order_api_response_result =  json_encode($order_api_response->getResult());
            $order_api_response_result = json_decode( $order_api_response_result ,true);
            $orderIdFromSquare = $order_api_response_result['order']['id'];



            // Create a payment for the order
            $amount_money = new \Square\Models\Money();
            $amount_money->setAmount($Final_amount);
            $amount_money->setCurrency($location_info->getCurrency());
            
            $body = new \Square\Models\CreatePaymentRequest($token, $idempotencyKey,$amount_money);
            $body->setOrderId($orderIdFromSquare);
            $body->setReferenceId($order_id);
            $body->setLocationId($locationId);

            $response = $square_client->getPaymentsApi()->createPayment($body);


            if ($response->isSuccess()) {

            $data = json_encode($response->getResult());
            $result = json_decode( $data ,true);

            //Trancaction Table Data
            $TrancactionData['status'] = 'Success';
            //$TrancactionData['member_id'] = session()->get('logged_user');
            $TrancactionData['first_name'] = $address['name'];
            $TrancactionData['last_name'] = $address['last_name'];
            $TrancactionData['address'] = $address['address'];
            $TrancactionData['country'] = $address['country'];
            $TrancactionData['city'] = $address['city'];
            $TrancactionData['zip_code'] = $address['pincode'];
            if($address['country']=='Canada'){  $TrancactionData['state'] = $address['canada_state'];  }else{  $TrancactionData['state'] = $address['state'];}
            $TrancactionData['transaction_id'] =  $result['payment']['id'];
            $TrancactionData['payment_order_id'] =  $result['payment']['order_id'];
            $TrancactionData['transaction'] = json_encode($response->getResult());
            $TrancactionData['created_at'] =  date("Y-m-d H:i:s");
            $update = $this->TransactionModel->where('member_id', session()->get('logged_user'))
                                             ->where('order_id', $order_id )
                                             ->set($TrancactionData)->update();

            if( $update)
            {
                $this->creditsModel->where('order_id', $order_id )->where('member_id', session()->get('logged_user'))->set(array( 'is_active' => 1 , 'transaction_id' => $result['payment']['id']  ))->update();
                $this->cartModel->where('order_id', $order_id )->delete();
            }


            echo json_encode($response->getResult());


            } else {

                $data = json_encode($response->getErrors());
                $result = json_decode( $data ,true);
                //Trancaction Table Data
                $TrancactionData['status'] = 'Failed';
                // $TrancactionData['member_id'] = session()->get('logged_user');
                $TrancactionData['first_name'] = $address['name'];
                $TrancactionData['last_name'] = $address['last_name'];
                $TrancactionData['address'] = $address['address'];
                $TrancactionData['country'] = $address['country'];
                $TrancactionData['city'] = $address['city'];
                $TrancactionData['zip_code'] = $address['pincode'];
                if($address['country']=='Canada'){  $TrancactionData['state'] = $address['canada_state'];  }else{  $TrancactionData['state'] = $address['state'];}
                //$TrancactionData['order_id'] =   $order_id;
                $TrancactionData['transaction'] = json_encode($response->getErrors());
                $update = $this->TransactionModel->where('member_id', session()->get('logged_user'))
                                                 ->where('order_id', $order_id )
                                                 ->set($TrancactionData)->update();

                if( $update)
                {
                    $this->creditsModel->where('order_id', $order_id )->delete();
                    $this->cartModel->where('order_id', $order_id )->set(array('order_id'=>null))->update();
                }


                echo json_encode(array('errors' => $response->getErrors()));
            }



        } else {

            $errors = $order_api_response->getErrors();

        }


        } catch (ApiException $e) {

            echo json_encode(array('errors' => $e));

        }

    } catch (\Exception $e) {

        log_message('error', 'Exception: ' . $e->getMessage());

        echo 'An exception occurred: ' . $e->getMessage();

    } catch (\Error $e) {

        log_message('error', 'Error: ' . $e->getMessage());

        echo 'An error occurred: ' . $e->getMessage();
    }

}






    public function payment_success( $local_order_id  = null)
    { 
        if( $local_order_id != null)
        {

            $data['TransactionData'] = $this->TransactionModel->where('order_id', $local_order_id )->where('member_id', session()->get('logged_user'))->find();
            if($data['TransactionData']){

                $memberCredits = $this->creditsModel->where('order_id', $local_order_id )
                                                    ->where('member_id', session()->get('logged_user'))
                                                    ->select('package_name')
                                                    ->select('cost')
                                                    ->selectSum('credit_points', 'credit_points')
                                                    ->selectSum('cost', 'costSum')
                                                    ->selectCount('package_name', 'pack_count')
                                                    ->groupBy('package_name')->findAll();



                if($data['TransactionData'][0]['is_mail_triggered'] == 0){
                    $sendmail_controller = new Sendmail_controller();
                    $mail = $sendmail_controller->index(session()->get('logged_user_email') , $local_order_id , 5); 
                    if($mail == true){
                        $this->TransactionModel->where('order_id', $local_order_id )->set(array('is_mail_triggered'=>1))->update();
                    }

                    $admin_email = $this->RuleModel->select('value')->where('rule_key', 10 )->get()->getRow()->value;
                    $sendmail_controller->index($admin_email , $local_order_id , 5);
                }    

               $Subtotal = 0;
                foreach ($memberCredits as $key => $ele) {
                $Subtotal = $Subtotal + $ele['costSum'];
                }

                $data['memberCredits'] =$memberCredits;
                $data['order_id'] = $local_order_id;
                $timestamp = strtotime($data['TransactionData'][0]['created_at']);
                $data['formattedDate']  = date('l, F j, Y', $timestamp);
                $data['Subtotal'] = $Subtotal;
                $data['gst'] = $this->RuleModel->select('value')->where('rule_key', 3 )->get()->getRow()->value;
                $data['pst'] = $this->RuleModel->select('value')->where('rule_key', 4 )->get()->getRow()->value;
                $data['card_brand'] =  json_decode($data['TransactionData'][0]['transaction'] , true)['payment']['card_details']['card']['card_brand'];
                $data['last_4'] =  json_decode($data['TransactionData'][0]['transaction'] , true)['payment']['card_details']['card']['last_4'];


                echo view('payment',$data);

            }else{
                // echo 'invalid order_id';
                return redirect()->to(base_url());

            }

        }



    }



    public function payment_failed( $local_order_id  = null)
    { 
        if( $local_order_id != null)
        {
            $data['TransactionData'] = $this->TransactionModel->where('order_id', $local_order_id )->where('member_id', session()->get('logged_user'))->find();
            if($data['TransactionData']){

                $sendmail_controller = new Sendmail_controller();
                $mail = $sendmail_controller->index(session()->get('logged_user_email') , $local_order_id , 7); 
                $admin_email = $this->RuleModel->select('value')->where('rule_key', 10 )->get()->getRow()->value;
                $sendmail_controller->index($admin_email , $local_order_id , 7 ,'admin');
                $data['category'] = json_decode($data['TransactionData'][0]['transaction'] , true)[0]['category'];
                $data['code'] = json_decode($data['TransactionData'][0]['transaction'] , true)[0]['code'];
                $data['detail'] = json_decode($data['TransactionData'][0]['transaction'] , true)[0]['detail'];
                $data['order_id'] = $data['TransactionData'][0]['order_id'];
                $timestamp = strtotime($data['TransactionData'][0]['created_at']);
                $data['formattedDate']  = date('l, F j, Y', $timestamp);

                echo view('payment_failed',$data);

            }else{
                // echo 'invalid order_id';
                return redirect()->to(base_url());
            }
        }

    }




public function createCreditPackCatalogObject()
{

    include 'app/Libraries/LocationInfo.php';

   
    $gst = $this->RuleModel->select('value')->where('rule_key', 3 )->get()->getRow()->value;
    $pst = $this->RuleModel->select('value')->where('rule_key', 4 )->get()->getRow()->value;
    $idempotencyKey = $this->generateIdempotencyKey();
    $locationId = getenv('SQUARE_LOCATION_ID');
 
  
   // Initialize the Square Client
    $square_client = new SquareClient([
        'accessToken' => getenv('SQUARE_ACCESS_TOKEN'),
        'environment' => getenv('ENVIRONMENT'),
        'userAgentDetail' => 'golf_evo', // Replace with your app's user agent detail
    ]);



        $money1 = new \Square\Models\Money();
        $money1->setAmount(550*100);
        $money1->setCurrency($location_info->getCurrency());

        $money2 = new \Square\Models\Money();
        $money2->setAmount(1000*100);
        $money2->setCurrency($location_info->getCurrency());

    
        $item_variation_data = new \Square\Models\CatalogItemVariation();
        $item_variation_data->setItemId('#PaymentItems');
        $item_variation_data->setName('Evo Pack 1');
        $item_variation_data->setPricingType('FIXED_PRICING');
        $item_variation_data->setPriceMoney($money1);
    
        $catalog_object1 = new \Square\Models\CatalogObject('ITEM_VARIATION', '#creditPack1');
        $catalog_object1->setItemVariationData($item_variation_data);

        $item_variation_data2 = new \Square\Models\CatalogItemVariation();
        $item_variation_data2->setItemId('#PaymentItems');
        $item_variation_data2->setName('Evo Pack 2');
        $item_variation_data2->setPricingType('FIXED_PRICING');
        $item_variation_data2->setPriceMoney($money2);
    
        $catalog_object2 = new \Square\Models\CatalogObject('ITEM_VARIATION', '#creditPack2');
        $catalog_object2->setItemVariationData($item_variation_data2);
    

        $variations = [$catalog_object1 , $catalog_object2];

        $tax_data = new \Square\Models\CatalogTax();
        $tax_data->setName('GST/PST');
        $tax_data->setCalculationPhase('TAX_SUBTOTAL_PHASE');
        $tax_data->setInclusionType('ADDITIVE');
        $tax_data->setPercentage($gst + $pst);
    
        $catalog_object3 = new \Square\Models\CatalogObject('TAX', '#sales_tax');
        $catalog_object3->setTaxData($tax_data);
        //echo json_encode($catalog_object3);

        $tax_ids = ['#sales_tax'];
        $item_data = new \Square\Models\CatalogItem();
        $item_data->setName('Evo pack Items');
        $item_data->setTaxIds($tax_ids);
        $item_data->setVariations($variations);
        $item_data->setProductType('REGULAR');
    
        $catalog_object = new \Square\Models\CatalogObject('ITEM', '#PaymentItems');
        $catalog_object->setItemData($item_data);
    

    
        $objects = [$catalog_object, $catalog_object3];
        $catalog_object_batch = new \Square\Models\CatalogObjectBatch($objects);
    
        $batches = [$catalog_object_batch];
        $body = new \Square\Models\BatchUpsertCatalogObjectsRequest($idempotencyKey, $batches);
    
        $api_response = $square_client->getCatalogApi()->batchUpsertCatalogObjects($body);
    
        if ($api_response->isSuccess()) {
            $result = $api_response->getResult();
            echo json_encode($result);
        } else {
            $errors = $api_response->getErrors();
            echo json_encode($errors);
        }

}

function generateIdempotencyKey($length = 32) {
    // Define characters that can be used in the key
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    // Get the total number of characters
    $characterCount = strlen($characters);
    // Initialize the idempotency key
    $idempotencyKey = '';
    // Generate a random key of the specified length
    for ($i = 0; $i < $length; $i++) {
        $idempotencyKey .= $characters[random_int(0, $characterCount - 1)];
    }
    return $idempotencyKey;
}




}




   

