<?php

ini_set('display_errors', 'Off');
ini_set('error_reporting', E_ALL);

class ProductsController extends AppController
{

    var $uses = array('Expense', 'GroupExpense', 'Participant', 'DemoExpense', 'AccessInfo', 'User', 'Product', 'Wallet');
    public $components = array(
        'RequestHandler',
        'MobileDetect'
    );
    private $app_version = "1"; // 1= old expense date, 2= new expense date


    public function initialize()
    {

        $this->app_version = "1";  // 1=  old app; 2=new app; date related
        $this->setDefaultTimeStamp();
    }

    public function beforeFilter()
    {
        parent::beforeFilter(); // TODO: Change the autogenerated stub
    }

    public function beforeRender()
    {
//        parent::beforeRender();

//        $this->layout = 'visitor';
    }


    // product List API
    public function list()
    {

        list($data, $status, $status_desc, $error) = $this->processValidation('GET');

        $input = array();
        if (empty($status)) {

            $activeStatus = 1;
            $conditions = array('status' => $activeStatus);
            $this->loadModel('Product');
            $products = $this->Product->list($conditions);

            if(!empty($products)){

                $input["products"] = $products;

                $status = "+000";
                $status_desc = "SUCCESS.";

            } else {
                $status = "-995";
                $status_desc = "Product Not Found.";

            }

        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    // myproducts API
    public function myproducts()
    {
        list($data, $status, $status_desc, $error) = $this->processValidation('GET');

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('Product');
            $this->loadModel('Order');

            $activeStatus = 1;
            $productIds = array();
            $orderArr = array();
            $expenseTypeArr = [1,2,3];

            $orderConditions = array(
                'user_id' => $data['user_id'],
                'SUBSTR(order_unique_id,1,1)' => $data['expense_type'],
                'expire_date > ' => $this->getSystemCurrentTimeStamp(),
            );
            $orders = $this->Order->list($orderConditions);

            if(!empty($orders)){

                foreach($orders as $k => $order){
                    if(!in_array($order['Order']['product_id'], $productIds)){
                        $productIds[] = $order['Order']['product_id'];
                        $orderArr[] = $order['Order'];
                    }
                }

                $prodConditions = array(
                    'status' => $activeStatus,
                    'id' => $productIds
                );
                if(in_array($data['expense_type'], $expenseTypeArr)){
                    $prodConditions['expense_type'] = $data['expense_type'];
                }
                $products = $this->Product->list($prodConditions);

                $input["products"] = $products;
                $input["orders"] = $orderArr;

                $status = "+000";
                $status_desc = "SUCCESS.";

            } else {
                $status = "-994";
                $status_desc = "Order Not Found.";
            }

        }

        $this->processResponse($input, $data, $status, $status_desc);
    }


    // product buy API
    public function buy()
    {

        list($data, $status, $status_desc, $error) = $this->processValidation();

        if (empty($status)) {
            list($status, $status_desc) = $this->validateBuyProduct($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        $input = array();
        if (empty($status)) {

            $this->loadModel('Product');
            $this->loadModel('Order');
            $this->loadModel('OrderBilling');
            $this->loadModel('Transaction');
            $this->loadModel('Recurring');
            $this->loadModel('Wallet');

            $activeStatus = 1;
            $conditions = array(
                'id' => $data['product_id'],
                'sku' => $data['product_sku'],
                'status' => $activeStatus
            );
            $productData = $this->Product->list($conditions);

            if (!empty($productData)) {
                $product = $productData[0];

                // user wallet data
                $wConditions = array(
                    'user_id' => $data['user_id'],
                    'status' => $activeStatus
                );
                $userWallet = $this->Wallet->list($wConditions);
                $userWalletData = (isset($userWallet[0]['Wallet'])) ? $userWallet[0]['Wallet'] : array();


                // Insert into orders
                $orderInput = $this->preparingOrderInput($data, $product, $userObj['id']);
                $orderObj = $this->Order->add($orderInput);
                $input["order"] = $orderObj[1];
                unset($input["order"]['id']);

                if (isset($orderObj[1]['id']) && ($orderObj[1]['id'] > 0)) {

                    // Order_billings
                    $billingData = (isset($data['billing_info'])) ? $data['billing_info'] : array();
                    $orderBillingInput = $this->preparingOrderBillingInput($userObj, $orderObj[1]['id'], $billingData);
                    $orderBillingObj = $this->OrderBilling->add($orderBillingInput);

                    // transactions
                    $transactionInput = $this->preparingTransactionInput($data, $product, $orderObj[1], $userWalletData);
                    $transactionObj = $this->Transaction->add($transactionInput);
                }

                // incase Recurrings
                if ($product['type'] == 1)     // 0 = One Time, 1 = Recurring
                {
                    $recurringInput = $this->preparingRecurringInput($data, $product);
                    $recurringObj = $this->Recurring->add($recurringInput);
                }

                // Update user table expiry date
                $this->updateUserTableExpiryDate($data['user_id'], $product);

                $status = "+000";
                $status_desc = "SUCCESS.";
            } else {
                $status = "-995";
                $status_desc = "Product Not Found.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }


    private function preparingOrderBillingInput($user, $order_id, $billingData)
    {
        $returnData = array();
        $returnData['order_id'] = $order_id;
        $returnData['first_name'] = (isset($billingData['first_name'])) ? $billingData['first_name'] : $user['first_name'];
        $returnData['last_name'] = (isset($billingData['last_name'])) ? $billingData['last_name'] : $user['last_name'];
        $returnData['address1'] = (isset($billingData['address1'])) ? $billingData['address1'] : '';
        $returnData['address2'] = (isset($billingData['address2'])) ? $billingData['address2'] : '';
        $returnData['city'] = (isset($billingData['city'])) ? $billingData['city'] : '';
        $returnData['state'] = (isset($billingData['state'])) ? $billingData['state'] : '';
        $returnData['zip'] = (isset($billingData['zip'])) ? $billingData['zip'] : '';
        $returnData['country'] = (isset($billingData['country'])) ? $billingData['country'] : '';
        $returnData['phone'] = (isset($billingData['phone'])) ? $billingData['phone'] : '';
        $returnData['email'] = (isset($billingData['email'])) ? $billingData['email'] : $user['profile_id'];
        $returnData["created_date"] = $this->getSystemCurrentTimeStamp();
        $returnData["updated_date"] = $this->getSystemCurrentTimeStamp();

        return $returnData;
    }

    private function preparingTransactionInput($data, $product, $order, $userWalletData)
    {
        $returnData = array();
        $returnData['payment_id'] = $order['payment_id'];
        $returnData['user_id'] = $data['user_id'];
        $returnData['type'] = 1; // 1 = Purchase, 2 = Deposit
        $returnData['entity_id'] = $order['id']; //order_id / deposit_id
        $returnData['description'] = '';
        $returnData['product_price'] = $product['price'];
        $returnData['fee'] = 0;
        $returnData['gross'] = $product['price'];
        $returnData['cost'] = 0;
        $returnData['net'] = $product['price'];
        $returnData['currency_id'] = 1; // 1 = USD
        $returnData['money_flow'] = '-';
        $returnData['current_balance'] = (isset($userWalletData['balance']))? $userWalletData['balance'] : 0;
        $returnData['status'] = 1; //0 = Pending, 1= Paid, 2 = Refund, 3 = Payment Fail
        $returnData["created_date"] = $this->getSystemCurrentTimeStamp();
        $returnData["updated_date"] = $this->getSystemCurrentTimeStamp();

        return $returnData;
    }

    private function preparingRecurringInput($data, $product)
    {
        /*
         * id
         * user_id
         * product_id
         * expense_type 1=Group, 2= Mess, 3 = Family
         * next_action_date
         * amount
         * total_amount
         * payment_number Total number of installments
         * payment_interval after how many payment cycle
         * payment_cycle D, W, M, Y
         * created_date
         * updated_date
         * */


        $returnData = array();
        $returnData['user_id'] = $data['user_id'];
        $returnData['product_id'] = $data['product_id'];
        $returnData['expense_type'] = $product['expense_type'];
        $returnData['product_price'] = $product['price'];
        $returnData["start_date"] = $this->getSystemCurrentTimeStamp();
        $returnData['next_action_date'] = $this->getNextActionDate($product, $returnData["start_date"]);
        $returnData["amount"] = $data['amount']; // for recurring product
        $returnData['total_amount'] = $data['amount'] * $product['payment_number'];
        $returnData['payment_number'] = $product['payment_number']; //Total number of installments
        $returnData["payment_interval"] = $product['payment_interval']; // after how many payment cycle
        $returnData['payment_cycle'] = $product['payment_cycle']; // D, W, M, Y
        $returnData["created_date"] = $this->getSystemCurrentTimeStamp();
        $returnData["updated_date"] = $this->getSystemCurrentTimeStamp();

        return $returnData;
    }

    private function getNextActionDate($product, $start_date)
    {
        if ($product['type']) { // if recurring
            $intervalType = 0; // day
            if ($product['payment_interval'] > 0) {

                switch ($product['payment_cycle']) {
                    case "D":
                        $unit = $product['payment_interval'];
                        break;
                    case "W":
                        $unit = $product['payment_interval'] * 7;
                        break;
                    case "M":
                        $intervalType = 1;
                        $unit = $product['payment_interval'];
                        break;
                    case "Y":
                        $intervalType = 2;
                        $unit = $product['payment_interval'];
                        break;
                    default:
                        $unit = 0;
                }
            }

            if ($intervalType == 1) { // month
                return date('Y-m-d H:i:s', strtotime('+' . $unit . ' months', strtotime($start_date)));
            } elseif ($intervalType == 2) { // year
                return date('Y-m-d H:i:s', strtotime('+' . $unit . ' years', strtotime($start_date)));
            } else {
                return date('Y-m-d H:i:s', strtotime('+' . $unit . ' days', strtotime($start_date)));
            }
        }
        return false;
    }

    private function preparingOrderInput($data, $product, $user_id)
    {
        $returnData = array();
        $returnData['payment_id'] = $this->systemGeneratedUniqueId($user_id, $product['expense_type']);
        $order_unique_id = $this->orderUniqueId($data, $product['expense_type']);
        $returnData['order_unique_id'] = $order_unique_id;
        $returnData['purchase_token'] = hash('sha256',$order_unique_id);
        $returnData['user_id'] = $data['user_id'];
        $returnData['product_id'] = $data['product_id'];
        $returnData['expire_date'] = $this->getProductExpireDate($product);
        $returnData['product_price'] = $product['price'];
        $returnData['fee'] = 0;
        $returnData['gross'] = $product['price'];
        $returnData['cost'] = 0;
        $returnData['net'] = $product['price'];
        $returnData['currency_id'] = $product['currency_id'];
        $returnData['platform_id'] = $data['platform_id']; // 1=iOS,2=Android,3=Windows
        $returnData["device_id"] = session_id();
        $returnData['status'] = 1; //0 = Pending, 1= Paid, 2 = Refund, 3 = Payment Fail
        $returnData['type'] = $product['type']; //0 = One Time, 1 = Recurring
        $returnData["user_ip"] = $this->getClientIp();
        $returnData['payment_type_id'] = $data['payment_type_id'];
        $returnData["created_date"] = $this->getSystemCurrentTimeStamp();
        $returnData["updated_date"] = $this->getSystemCurrentTimeStamp();

        return $returnData;
    }

    private function orderUniqueId($data, $expense_type)
    {
        return $expense_type . '-' . $data['user_id'] . '-' . time();
    }

    private function updateUserTableExpiryDate($user_id, $product)
    {
        $status = false;
        if ($user_id > 0) {
            switch ($product['expense_type']) {
                case "1":
                    $fields['group_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
                    if ($this->User->updateFieldsById($user_id, $fields)) {
                        $status = true;
                    }
                    break;
                case "2":
                    $fields['mess_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
                    if ($this->User->updateFieldsById($user_id, $fields)) {
                        $status = true;
                    }
                    break;
                case "3":
                    $fields['family_expiry_date'] = '"' . $this->getProductExpireDate($product) . '"';
                    if ($this->User->updateFieldsById($user_id, $fields)) {
                        $status = true;
                    }
                    break;
                default:
                    // do nothing
                    break;
            }
        }
        return $status;
    }

    private function getProductExpireDate($product)
    {
        $unit = 0;
        $intervalType = 0; // day
        if ($product['payment_interval'] > 0) {

            switch ($product['payment_cycle']) {
                case "D":
                    $unit = $product['payment_interval'];
                    break;
                case "W":
                    $unit = $product['payment_interval'] * 7;
                    break;
                case "M":
                    $intervalType = 1;
                    $unit = $product['payment_interval'];
                    break;
                case "Y":
                    $intervalType = 2;
                    $unit = $product['payment_interval'];
                    break;
                default:
                    $unit = 0;
            }
        }
        if ($intervalType == 1) { // month
            return date('Y-m-d H:i:s', strtotime('+' . $unit . ' months'));
        } elseif ($intervalType == 2) { // year
            return date('Y-m-d H:i:s', strtotime('+' . $unit . ' years'));
        } else {
            return date('Y-m-d H:i:s', strtotime('+' . $unit . ' days'));
        }
    }


    private function validateBuyProduct($data)
    {

        //check validity
        $error = "";
        $error_desc = "";


        if (empty($error)) {
            if (!array_key_exists('product_id', $data)
                || !array_key_exists('product_sku', $data)
                || !array_key_exists('user_id', $data)
            ) {
                $error = "6";
                $error_desc = "product_id, product_sku and user_id are required";
            }
        }

        if (empty($error)) {
            if (array_key_exists('billing_info', $data)) {

                if (array_key_exists('phone', $data['billing_info']) && ($data['billing_info']['phone'] != '')) {
                    if (!is_numeric($data['billing_info']['phone'])) {
                        $error = "7";
                        $error_desc = "phone number must be numeric";
                    }
                }
            }
        }
        if (empty($error)) {
            if (array_key_exists('billing_info', $data)) {

                if (array_key_exists('zip', $data['billing_info']) && ($data['billing_info']['zip'] != '')) {
                    if (!is_numeric($data['billing_info']['zip'])) {
                        $error = "8";
                        $error_desc = "zip code must be numeric";
                    }
                }
            }
        }
        if (empty($error)) {
            if (array_key_exists('billing_info', $data)) {
                if (array_key_exists('email', $data['billing_info'])) {
                    $regex = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
                    if (!preg_match($regex, $data['billing_info']['email'])) {
                        $error = "9";
                        $error_desc = "email address is invalid";
                    }
                }
            }
        }

        return array($error, $error_desc);
    }


}
