<?php
namespace App\Controllers\Client;
use App\Controllers\BaseController;
use App\Core\Service\Logger;
use App\Model\OrderModel;
use App\Model\FxModel;
use App\Library\Shopify;
use App\Library\Fx;

class ShopifyController extends BaseController
{   
    private $FxModel;
    private $OrderModel;
    private $Fx;
    public function __construct() {
        parent::__construct();
        $this->FxModel     = new FxModel();
        $this->OrderModel  = new OrderModel();
        $this->Fx = new Fx();
    }

    public function addOrderToShopifyProcess() {
        try {
            $rules = [
                'order_id'=> array('rules' => 'required', 'label' => "Order Id"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $order_id = is_array($this->input['order_id']) ? implode(',', $this->input['order_id']) : $this->input['order_id'];
            $orsp = $this->FxModel->getOrderDetailForCourier($this->user_data->comp_id, "t1.id IN(".$order_id.") AND (shopify_id IS NULL OR shopify_id=0)", 0);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Order detail not found', 'data' => null));
            }
            
            $insrs = $this->FxModel->addOrderShopifyLog($this->user_data->comp_id, $this->user_data->id, $orsp['data']);
            if(empty($insrs['status'])) {
                throw new \Exception($insrs['error']);
            }
            $this->Kafkam->sendMessage("sanordo_move_order_shopify", ['comp_id'=>$this->user_data->comp_id, 'user_id'=>$this->user_data->id]);
            $this->sendResponse(array('code' => 200, 'message' => 'Orders are queued in the process of shopify. Please check logs', 'data'=> null)); 
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 400, 'message' => "Something went wrong while moving order to Shopify", 'data' => $e->getMessage()));
        }
    }

    public function moveOrderToShopify($comp_id) {
        try {
            $comp = $this->Fx->getCompanyDetail($comp_id);
            if(empty($comp)) {
                throw new \Exception($comp['error']);
            }
            if(empty($comp['data'])) {
                throw new \Exception("Company detail not found to process shopify orders");
            }
            
            if(empty($comp['data']['api_url']) || empty($comp['data']['shopify_api_key']) || 
            empty($comp['data']['shopify_api_secret_key']) || empty($comp['data']['shopify_access_token'])) {
                throw new \Exception("Shopify configuration is incomplete for company:".$comp['data']['name']." to process shopify orders. Provide all required settings.(API version, Store Name, API Key, Secret Key and Access Token)");
            }
            $tbl = $this->FxModel->client_db_prefix.$comp_id . "." . $this->FxModel->tables['order_shopify_process_log'];
            $orsp = $this->FxModel->fetchAllData("SELECT * FROM $tbl WHERE status=:st", [":st"=>0]);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(!empty($orsp['data'])) {
                $shopifyLib = new Shopify($comp['data']); 
                foreach($orsp['data'] as $log) {
                    if($log['status'] == 0) {
                        $updrs = $this->FxModel->update($tbl, ['status'=>3], ['order_id'=>$log['order_id']]);
                        if(empty($updrs['status'])) {
                            Logger::error($updrs['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
                        }
                        $resp = $this->processOrderToShopify($comp['data'], $log, $shopifyLib);
                        $updata = [];
                        if(empty($resp['status'])) {
                            $updata['status'] = 2;
                            $updata['failed_reason'] = $resp['error'];
                        } else {
                            $updata['status'] = 1;
                        }
                        $updrs1 = $this->FxModel->update($tbl, $updata, ['order_id'=>$log['order_id']]);
                        if(empty($updrs1['status'])) {
                            Logger::error($updrs1['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
                        } else {
                            Logger::debug("Order ID:".$log['order_id']." is processed to shopify", ['File' => __FILE__, 'Line'=>__LINE__]);
                        }
                    }
                }
                Logger::debug('Shopify processing completed', ['File' => __FILE__, 'Line'=>__LINE__]);
            } else {
                Logger::debug('No orders to process for Shopify', ['File' => __FILE__, 'Line'=>__LINE__]);
            }
            return ["status"=>true];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line'=>$e->getLine()]);
            return ["status"=>false];
        }
    }

    private function processOrderToShopify($company, $log, Shopify $shopifyLib) {
        try {
            $orsp = $this->FxModel->getOrderDetailForCourier($company['id'], "t1.id=".$log['order_id'], 1);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                throw new \Exception('Order detail not found');
            }
            if(!empty($orsp['data']['shopify_id'])) {
                throw new \Exception('Already moved to shopify');
            }
            $arsp = $this->FxModel->getOrderFullAddressDetail($company['id'], $orsp['data']);
            if(empty($arsp['status'])) {
                throw new \Exception($arsp['error']);
            }
            $orsp['data'] = $arsp['data'];
            $orsp['data']['customer_detail'] = !empty($orsp['data']['customer_detail']) ? json_decode($orsp['data']['customer_detail'], true) : [];
            $mobile_no = '';
            if(!empty($orsp['data']['customer_detail']['country_code']) && 
            !empty($orsp['data']['customer_detail']['mobile_number'])) {
                $mobile_no = trim($orsp['data']['customer_detail']['country_code']).trim($orsp['data']['customer_detail']['mobile_number']);
            } else if(!empty($orsp['data']['customer_detail']['mobile_number'])) {
                $mobile_no = trim($orsp['data']['customer_detail']['mobile_number']);
            }
            if(empty($mobile_no)) {
                throw new \Exception("Customer's Mobile no not found in order detail to process shopify orders");
            }
            $ordItemrs = $this->OrderModel->getOrderItemList($company['id'], "order_id=".$orsp['data']['id'], 0, 1);
            if(empty($ordItemrs['status'])) {
                throw new \Exception($ordItemrs['error']);
            }
            if(empty($ordItemrs['data'])) {
                throw new \Exception("Order Item detail not found");
            }

            $item_total_qty = $this->FxModel->getOrderItemsTotalQty($company['id'], $orsp['data']['id']);
            if(empty($item_total_qty['status'])) {
                throw new \Exception($item_total_qty['error']);
            }
            $orsp['data']['total_item_qty'] = $item_total_qty['data'];

            $custrs = $shopifyLib->getCustomer($mobile_no);
            if(empty($custrs['status'])) {
                throw new \Exception($custrs['error']);
            }

            $log_data = [
                "order_id"  => $orsp['data']['id'],
                "status"    => $custrs['order_status'],
                "url"       => $custrs['url'],
                "request_method"  => $custrs['request_method'],
                "headers"   => $custrs['headers'],
                "request"   => $custrs['api_request'],
                "response"  => $custrs['api_response'],
                "cr_usr"    => $orsp['data']['order_created_by_id'],
                "type"      => "GET_CUSTOMER"
            ];
            $inslog_id = $this->createShopifyLog($company['id'], $log_data);
            
            $shopify_customer_id = !empty($custrs['data']) ? $custrs['data'] : 0;
            $crustrs = $shopifyLib->addUpdateCustomer($orsp['data'], $shopify_customer_id);
            
            if(empty($crustrs['status'])) {
                throw new \Exception($crustrs['error']);
            }
            $log_data = [
                "order_id"  => $orsp['data']['id'],
                "status"    => $crustrs['order_status'],
                "url"       => $crustrs['url'],
                "request_method"  => $crustrs['request_method'],
                "headers"   => $crustrs['headers'],
                "request"   => $crustrs['api_request'],
                "response"  => $crustrs['api_response'],
                "cr_usr"    => $orsp['data']['order_created_by_id'],
                "type"      => "ADD_UPDATE_CUSTOMER"
            ];

            $inslog_id = $this->createShopifyLog($company['id'], $log_data);
            
            if(empty($crustrs['data'])) {
                throw new \Exception("Unable to add/update shopify customer");
            } 
            $shopify_customer_id = $crustrs['data'];

            $shopify_data = $shopifyLib->prepareOrderData($orsp['data'], $ordItemrs['data'], $shopify_customer_id);
            if(empty($shopify_data['status'])) {
                throw new \Exception($shopify_data['error']);
            }
            if(empty($shopify_data['data'])) {
                throw new \Exception("Unable to preapre data to create order on shopify");
            }
            foreach($shopify_data['data']['order']['line_items'] as $index => $item) {
                if(!empty($item['variant_id']) && !empty($ordItemrs['data'][$index]['variant_id']) && 
                $item['variant_id'] != $ordItemrs['data'][$index]['variant_id']) {
                    $this->updateItem($company['id'], ['variant_id'=>$item['variant_id']], ['item_id'=>$ordItemrs['data'][$index]['item_id']]);
                }
            }
            $shopify_order = $shopifyLib->createOrder($shopify_data['data']);
            if(empty($shopify_order['status'])) {
                throw new \Exception($shopify_order['error']);
            }
            $log_data = [
                "order_id"  => $orsp['data']['id'],
                "status"    => $shopify_order['order_status'],
                "url"       => $shopify_order['url'],
                "request_method"  => $shopify_order['request_method'],
                "headers"   => $shopify_order['headers'],
                "request"   => $shopify_order['api_request'],
                "response"  => $shopify_order['api_response'],
                "cr_usr"    => $orsp['data']['order_created_by_id'],
                "type"      => "CREATE_ORDER"
            ];
            $shopify_log_id = $this->createShopifyLog($company['id'], $log_data);
            if(empty($shopify_order['data'])) {
                throw new \Exception("Shopify Id is not getting received from API. Unable to create order on Shopify");
            }
            $this->updateOrder( $company['id'],  
                [
                    "shopify_id"=>$shopify_order['data']['shopify_id'],
                    "shopify_number"=>$shopify_order['data']['shopify_number'],
                    "shopify_log_id"=> !empty($shopify_log_id) ? $shopify_log_id : NULL
                ],
                ['id'=>$orsp['data']['id']]
            );
            return ["status"=>true];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line'=>$e->getLine()]);
            return ["status"=>false, "error"=>$e->getMessage()];
        }
    }

    private function createShopifyLog(Int $comp_id, Array $log_data) {
        try {
            $tbl = $this->FxModel->client_db_prefix.$comp_id . "." . $this->FxModel->tables['order_shopify_log'];
            $insrs = $this->FxModel->insert($tbl, $log_data);
            if(empty($insrs['status'])) {
                Logger::error($insrs['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
            }
            return $insrs['insert_id'];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line'=>$e->getLine()]);
            return 0;
        }
    }

    private function updateItem(Int $comp_id, Array $data, Array $where) {
        try {
            $tbl = $this->FxModel->client_db_prefix.$comp_id . "." . $this->FxModel->tables['item_master'];
            $insrs = $this->FxModel->update($tbl, $data, $where);
            if(empty($insrs['status'])) {
                Logger::error($insrs['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
            }
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line'=>$e->getLine()]);
        }
    }

    private function updateOrder(Int $comp_id, Array $data, Array $where) {
        try {
            $tbl = $this->FxModel->client_db_prefix.$comp_id . "." . $this->FxModel->tables['order'];
            $insrs = $this->FxModel->update($tbl, $data, $where);
            if(empty($insrs['status'])) {
                Logger::error($insrs['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
            }
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line'=>$e->getLine()]);
        }
    }
}