<?php

/**
 * order_sales table's controller.
 *
 * Used to perform operations on order_sales table.
 *
 * @author Mario Vallejo <wappsi.desarrollomovil01@gmail.com>
 */

namespace App\Controllers;

use App\Models\SmaOrderSalesModel;
use CodeIgniter\RESTful\ResourceController;
use NumberFormatter;

class SmaOrderSales extends ResourceController
{

    /**
     * Get updated order_sales table's rows.
     *
     * 
     * Based on last_sync value (from request), return updated rows from order_sales.
     *
     * Request should contain last_sync value (date) to get updated rows based on
     * that date.
     *
     * If request contains first_time = true, it returns all data in table.
     *
     *
     * @return HttpResponse
     */
    public function sync()
    {

        $rules = [
            'last_sync' => 'valid_date',
        ];
        $this->request;
        $message = [
            'last_sync' => [
                'required' => 'Tipo de dato no valido',
            ],

        ];
        if (!$this->validate($rules, $message)) {

            // if validation fails

            $response = [
                'status' => 400,
                'error' => true,
                'message' => $this->validator->getErrors(),
                'data' => [],
                'date' => $this->request->getVar('last_sync'),
            ];

            return $this->respondCreated($response);
        } else {
            $this->setModel(new SmaOrderSalesModel($this->dbGroupFromRequest()));

            // validate
            $order_sales = [];
            $orders_items = [];
            helper('jwt');
            $authHeader = $this->request->getServer('HTTP_AUTHORIZATION');
            $token = getJWTFromRequest($authHeader);
            $view_right = viewRightFromJWT($token);

            $filter_to_all = [];
            $filter_to_update = null;

            // to get only last month orders

            $first_day = date('Y-m-01 00:00:00');

            // to get current month sales only
            $filter_to_all = ['last_update >' => "$first_day"];

            if ($view_right == 0) {
                $uId = userIdFromJWT($authHeader);
                $filter_to_all['created_by'] = $uId;
                $filter_to_update = ['created_by' => $uId];
                // print_r($filter_to_all);
            }

            if (($this->request->getVar('first_time') ?? false) == true) {

                $order_sales = $this->getAllRows(['id' => 'id_cloud'], $filter_to_all);
            } else if (($this->request->getVar('first_time') ?? false) == false) {

                $order_sales = $this->getUpdatedRows(['id' => 'id_cloud'], $filter_to_update);
            } else {
                $response = [
                    'status' => 400,
                    'error' => true,
                    'message' => 'EL campo "first_time" no es valido',
                    'data' => [],
                ];

                return $this->respondCreated($response);
            }

            // now get orderItems
            for ($i = 0; $i < count($order_sales); $i++) {
                $items = SmaOrderSaleItems::getOrderItems($order_sales[$i]['id_cloud'], $this->dbGroupFromRequest(),);
                array_push($orders_items, $items);
            }

            $response = [
                'status' => 200,
                'error' => false,
                'message' => 'Exito',
                'server_date_time' => $this->getServerDateTime(),
                'data' => [
                    'sma_order_sales' => $order_sales,
                    'sma_order_sale_items' => $orders_items,

                ],
            ];
            return $this->respondCreated($response);
        }
    }



    /**
     * Find new orders with given params.
     *
     * 
     * Based on filter, query, listed_orders_id and limit, search for new orderSales.
     *
     * Request should contain those values.
     *
     * @return HttpResponse
     */
    public function findOrders()
    {

        $rules = [
            'limit' => 'integer',
            "biller_id" => "integer"
        ];
        $this->request;
        $message = [
            'limit' => [
                'integer' => 'Tipo de dato no valido',
            ],
            'biller_id' => [
                'integer' => 'Tipo de dato no valido',
            ],
        ];
        if (!$this->validate($rules, $message)) {

            // if validation fails

            $response = [
                'status' => 400,
                'error' => true,
                'message' => $this->validator->getErrors(),
                'data' => [],
            ];

            return $this->respondCreated($response);
        } else {
            $this->setModel(new SmaOrderSalesModel($this->dbGroupFromRequest()));


            // validate
            $order_sales = [];
            $orders_items = [];
            helper('jwt');
            $authHeader = $this->request->getServer('HTTP_AUTHORIZATION');
            $token = getJWTFromRequest($authHeader);
            $view_right = viewRightFromJWT($token);

            $where = [];

            if ($view_right == 0) {
                $uId = userIdFromJWT($authHeader);
                $where['created_by'] = $uId;
                // print_r($where);
            }

            /// Add biller_id where and condition
            $where["biller_id"] = $this->request->getVar('biller_id');

            // To not take cancelled sales
            $where['sale_status!='] = "cancelled";

            $select = "";

            try {

                // Select allowedRFields to app in model

                $fields = $this->model->allowedFieldsToApp ?? [];

                // replace "id" to "id_cloud", if needed
                $index = array_search('id', $fields);
                if ($index !== FALSE) {
                    $fields[$index] = "id AS id_cloud";
                }
                $select = implode(",", $fields) ?? "*";
            } catch (\Throwable $th) {
                //throw $th;
                $select = implode(",", $this->model->allowedFieldsToApp ?? []) ?? "*";
            }
            // select




            $this->model->select($select);

            $this->model->where($where);


            // now to filter order by status
            if (!empty($this->request->getVar('query') ?? "")) {
                $search = $this->request->getVar('query');
                $this->model->where('(customer LIKE "%' . $search . '%" OR note LIKE "%' .
                    $search . '%" OR staff_note LIKE "%' . $search . '%" OR reference_no LIKE "%' . $search . '%")');
            }

            // now to filter order by status
            if (!empty($this->request->getVar('status_filter') ?? [])) {
                $this->model->whereIn("sale_status", $this->request->getVar('status_filter'));
            }

            // now to filter order by status
            if (!empty($this->request->getVar('local_orders') ?? [])) {
                $this->model->whereNotIn("id", $this->request->getVar('local_orders'));
            }

            $this->model->orderBy('registration_date', 'DESC');

            $this->model->limit($this->request->getVar('limit') ?? 30);

            // get query

            $order_sales = $this->model->get()
                ->getResultArray();
            // var_dump($order_sales);
            // now get orderItems
            if (!empty($order_sales ?? [])) {
                for ($i = 0; $i < count($order_sales); $i++) {
                    $items = SmaOrderSaleItems::getOrderItems($order_sales[$i]['id_cloud'], $this->dbGroupFromRequest(),);
                    array_push($orders_items, $items);
                }
            }

            $response = [
                'status' => 200,
                'error' => false,
                'message' => 'Exito',
                'server_date_time' => $this->getServerDateTime(),
                'data' => [
                    'sma_order_sales' => $order_sales,
                    'sma_order_sale_items' => $orders_items,

                ],
            ];
            return $this->respondCreated($response);
        }
    }

    /**
     * Creates a new order sale given order sale data sended by a http post.
     *
     * Given order_sales and order_sale_items data on request, try to create a new order
     * sale row, with it's order_sale_items rows.
     * 
     * @todo Create validation rules and messages for order_sales and order_sale_items 
     * 
     * @return HttpResponse 
     */
    function new()
    {
        $rules = [
            // // for some reason it doesnt detect it
            // 'order_sales' => 'required|json_valid_fields['
            // .''
            // .']',
            'order_sale_items' => 'required',
        ];
        $message = [
            // 'order_sales' => [
            //     'required' => 'Es necesaria la información de el pedido para su creación',
            // ],
            'order_sale_items' => [
                'required' => 'Es necesaria la información de los productos del pedido para su creación',
            ],

        ];

        if (!$this->validate($rules, $message)) {

            // if validation fails

            $response = [
                'status' => 400,
                'error' => true,
                'message' => $this->validator->getErrors(),
                'data' => [],
            ];

            return $this->respondCreated($response);
        } else {
            $orderInfoArray = ($this->request->getJsonVar("order_sales", true) ?? null);
            // validate if order_sales info is in request

            $response = [];

            $min_sale_ammount = 0;

            try {
                // Customer orders count
                $customer_orders_count = $this->customerOrdersOnCurrentDay($orderInfoArray['customer_id'], $this->dbGroupFromRequest(),);
                if (!($customer_orders_count > 0)) {
                    $min_sale_ammount = SmaBillerData::billerMinOSaleAmmount($orderInfoArray["biller_id"], $this->dbGroupFromRequest(),);
                }
            } catch (\Throwable $th) {
                //throw $th;
            }

            $grand_total = $orderInfoArray["grand_total"];

            if ($grand_total >= $min_sale_ammount) {
                if ($orderInfoArray != null) {
                    // set order origin to seller app
                    $orderInfoArray["order_sale_origin"] = 2;
                    // get order items data
                    $orderItemsInfoArray = ($this->request->getJsonVar("order_sale_items", true));

                    //insert order data into order_sales model

                    $this->setModel(new SmaOrderSalesModel($this->dbGroupFromRequest()));

                    $refNo = null;

                    try {

                        $refNo = SmaDocumentsTypes::getReferenceNo($orderInfoArray['document_type_id'], $this->dbGroupFromRequest(),);
                        // $refNo=0;
                        if (isset($refNo)) {
                            $orderInfoArray['reference_no'] = $refNo;
                        }

                        // print_r($orderItemsInfoArray);

                        $orderSaleId = $this->model->insert($orderInfoArray, true);

                        if ($orderSaleId ?? false) {
                            // switch to OrderSaleItemModel

                            $result = SmaOrderSaleItems::insertOrderItems($orderItemsInfoArray, $orderSaleId, $this->dbGroupFromRequest());
                            // check everythings goes nice
                            if ($result != false && $result == count($orderItemsInfoArray)) {
                                // send email to notify new order
                                helper('email');
                                sendOrderEmail($orderInfoArray, $orderItemsInfoArray,$this->dbGroupFromRequest());
                                $response = [
                                    'status' => 201,
                                    'error' => false,
                                    'message' => "Pedido registrado",
                                    'data' => [
                                        'order_sale_id' => $orderSaleId,
                                        'reference_no' => $refNo,
                                        'server_date' => $this->getServerDateTime(),
                                    ],
                                ];
                            } else {
                                //if neeeded we can undo document consecutive
                                // if(isset($refNo)){
                                //     SmaDocumentsTypes::undoReferenceNo($orderInfoArray['document_type_id']);
                                // }

                                // set orderSale status to error
                                $this->disableOrderSale($orderSaleId, $this->dbGroupFromRequest());

                                $response = [
                                    'status' => 400,
                                    'error' => true,
                                    'message' => "Eror al registrar items de pedido",
                                    'data' => [],
                                ];
                            }
                        }
                    } catch (\Throwable $th) {
                        //if neeeded we can undo document consecutive
                        // if(isset($refNo)){
                        //     SmaDocumentsTypes::undoReferenceNo($orderInfoArray['document_type_id']);
                        // }

                        // if orderSales was inserted to db, then set status to error
                        if ($orderSaleId ?? false) {
                            $this->disableOrderSale($orderSaleId, $this->dbGroupFromRequest());
                        }

                        $response = [
                            'status' => 400,
                            'error' => true,
                            'message' => "Eror al registrar el pedido",
                            'error_message' => "$th",
                            'data' => [],
                        ];
                    }
                } else {
                    $response = [
                        'status' => 400,
                        'error' => true,
                        'message' => "El campo order_sales es necesario",
                        'data' => [],
                    ];
                }
            } else {
                $fmt = new NumberFormatter('COP', NumberFormatter::CURRENCY);

                $response = [
                    'status' => 400,
                    'error' => true,
                    'message' => "El pedido no cumple el minimo requerido (" . $fmt->formatCurrency($min_sale_ammount, "COP") . ")",
                    'data' => [],
                ];
            }


            return $this->respondCreated($response);
        }
    }

    public function test()
    {
        return $this->respondCreated([
            'data' => $this->customerOrdersOnCurrentDay(1106, $this->dbGroupFromRequest())
        ]);
    }

    /**
     * Disable an order_sale row.
     * 
     * Use when and OrderSale row is needed to be disabled.
     *
     * @param integer $orderSaleId
     * @return bool
     */
    public static function disableOrderSale($orderSaleId, String $dbGroup)
    {
        try {
            $orderSModel = new SmaOrderSalesModel($dbGroup);
            // echo $orderSaleId;
            $result = $orderSModel->update($orderSaleId, ['sale_status' => 'error']);
            // echo $result?1:0;
            return $result;
        } catch (\Throwable $th) {
            // echo "$th";
            return false;
        }
    }

    /**
     * Customer orders count (in current day)
     *
     * Returns count of order_sales for a given customer.
     * 
     * @param int  $customer_id   Customer id
     *
     *
     * @return  int If returns 0, maybe value isn't define
     * @author Mario Vallejo <wappsi.desarrollomovil01@gmail.com>
     */
    static public function customerOrdersOnCurrentDay(int $customer_id, String $dbGroup)
    {
        $model = new SmaOrderSalesModel($dbGroup);
        $current_date = date("Y-m-d");
        try {
            $customer_orders_count =  $model->where("registration_date >", $current_date)
                ->where("customer_id", $customer_id);
            // print_r($customer_orders_count);
            return $customer_orders_count->countAllResults();
        } catch (\Throwable $th) {
            // throw $th;
            return 0;
        }
    }

    /**
     * Cancel an order sale.
     *
     * 
     * Based on order_id value (from request), change sale_Status to "cancelled" of an orderSale 
     * if it´s current status is "pending".
     *
     *
     *
     * @return HttpResponse
     */
    public function cancellPendingOrder()
    {

        $rules = [
            'order_id' => 'integer|required',
        ];
        $this->request;
        $message = [
            'order_id' => [
                'required' => 'Order id required',
                'integer' => 'Order id must be an integer',
            ],

        ];
        if (!$this->validate($rules, $message)) {

            // if validation fails

            $response = [
                'status' => 400,
                'error' => true,
                'message' => $this->validator->getErrors(),
                'data' => []
            ];

            return $this->respondCreated($response);
        } else {
            $this->setModel(new SmaOrderSalesModel($this->dbGroupFromRequest()));

            $order_sales = $this->model->where('id', $this->request->getVar('order_id'))
                ->where('sale_status', 'pending')
                ->set('sale_status', 'cancelled')
                ->set('last_update', $this->getServerDateTime())
                ->update();
            $response = [
                'status' => 200,
                'error' => false,
                'message' => 'Exito',
                'server_date_time' => $this->getServerDateTime()
            ];
            return $this->respondCreated($response);
        }
    }
}
