<?php
declare(strict_types=1);

namespace App\Controller;

use App\Lib\Controller;
use App\Models\{TokenMiddleware, Orders, Restaurant, Customer, Dish, Customizations, Menu};
use App\Util\Helper;

class OrdersController
{
    protected $tokenData;
    protected TokenMiddleware $tokenMiddleware;
    public function __construct()
    {
        $this->tokenMiddleware = new TokenMiddleware();
        $this->tokenData = $this->tokenMiddleware->getData();
    }

    public function getOrder(int|string $orderReference)
    {
        if (empty($orderReference)) {
            @header("HTTP/1.1 400 Bad Request");
            return ["status" => false, "message" => "Sorry, order reference was not provided."];
        }

        $orders = new Orders;
        $restaurant = new Restaurant;
        $customer = new Customer;

        $restaurantId = (int) $this->tokenData['id'];
        $restaurantData = $restaurant->getById($restaurantId, 'id');
        $orderArray = $orders->getByReference($orderReference);
        $orderRequests = [];

        if(empty($restaurantData)){
            @header("HTTP/1.1 404 Not Found");
            return ["status" => false, "message" => "Sorry, this restaurant was not found."];
        }

        if(empty($orderArray)){
            @header("HTTP/1.1 404 Not Found");
            return ["status" => false, "message" => "Sorry, this order data was not found."];
        }

        $orderId = (int) $orderArray->order_id;
        $customerId = (int) $orderArray->customer_id;
        $orderCode = $orders->getReferenceCode($orderArray->order_type);
        $customerData = $customer->getById($customerId, 'customer_avatar');
        $orderData = $orders->getDataByOrderId($orderId);
        $itemsData = $orders->getItemsByOrderId($orderId);
        $requestData = $orders->getRequest($orderId);

        if($requestData){
            $requestArray = \json_decode($requestData->data, true);
            foreach($requestArray as $key => $value){
                $orderRequests[] = $value;
            }
        }

        $orderItems = [];
        $orderCustomisation = [];
        if($itemsData){
            foreach($itemsData as $item){
                $dishId = (int) $item->dish_id;
                $dishTitle = $item->dish_title;
                $dishQuantity = (int) $item->dish_quantity;
                $dishPrice = (float) $item->dish_price;

                $orderItems[] = [
                    'dish_id' => $dishId,
                    'dish_title' => $dishTitle,
                    'dish_quantity' => $dishQuantity,
                    'dish_price' => $dishPrice
                ];
            }
        }

        $orderStatusArray = ['pending' => 'Pending', 'accepted' => 'Accepted', 'declined' => 'Declined', 'completed' => 'Completed', 'on-hold' => 'On Hold'];
        $orderStatus = $orderStatusArray[$orderArray->order_status];
        if($orderArray->is_preparing == 'true'){
            $orderStatus = 'Preparing';
        }elseif($orderArray->in_transit == 'true'){
            $orderStatus = 'In Transit';
        }

        $dataResult = [
            'order_id' => $orderId,
            'reference' => \intval($orderArray->reference) ,
            'reference_code' => $orderCode . $orderArray->reference,
            'customer_id' => $customerId,
            'customer_name' => $orderData->customer_name,
            'customer_avatar' => $customer::$publicDirectory . '/' . $customerData->customer_avatar,
            'customer_address' => $orderArray->customer_address ?? '',
            'is_preparing' => $orderArray->is_preparing == 'true' ? true : false,
            'is_refunded' => $orderArray->is_refunded == 'true' ? true : false,
            'in_transit' => $orderArray->in_transit == 'true' ? true : false,
            'order_table_no' => \intval($orderArray->order_table_no) ,
            'order_total' => (float) $orderArray->order_total,
            'order_currency' => $orderArray->order_currency,
            'order_type' => $orderArray->order_type,
            'order_status' => $orderStatus,
            'order_note' => $orderArray->order_note,
            'created_at' => Helper::timeAgo($orderArray->created_at),
            'order_request' => $orderRequests,
            'order_items' => $orderItems,
            'order_customisation' => [],
            'order_rider' => []
        ];

        return ['status' => true, 'data' => $dataResult];
    }

    public function getOrders(string $action)
    {
        if (empty($action)) {
            @header("HTTP/1.1 401 Unauthorized");
            return ["status" => false, "message" => "Unauthorized access detected."];
        }

        $customer = new Customer;
        $restaurant = new Restaurant;
        $orders = new Orders;

        $restaurantId = (int) $this->tokenData['id'];
        $restaurantData = $restaurant->getById($restaurantId, 'id');
        if(empty($restaurantData)){
            @header("HTTP/1.1 404 Not Found");
            return ["status" => false, "message" => "Sorry, this restaurant was not found."];
        }

        if(\in_array($action, ['all', 'new', 'in_complete', 'complete', 'decline', 'delivery', 'takeaway', 'dine-in'])){

            $orderStatistics = $orders->getStatistics($restaurantId);
            $ordersArray = $orders->getAllByRestaurantIdCustom($restaurantId, '*', [
                'filter_by' => $action
            ]);
            $populateArray = [];

            if(!empty($ordersArray)):
                foreach($ordersArray as $val){
                    $orderId = (int) $val->order_id;
                    $customerId = (int) $val->customer_id;

                    $orderCode = $orders->getReferenceCode($val->order_type);
                    $customerData = $customer->getById($customerId, 'customer_avatar');
                    $orderData = $orders->getDataByOrderId($orderId);

                    $orderStatusArray = ['pending' => 'Pending', 'accepted' => 'Accepted', 'declined' => 'Declined', 'completed' => 'Completed', 'on-hold' => 'On Hold'];
                    $orderStatus = $orderStatusArray[$val->order_status];
                    if($val->is_preparing == 'true'){
                        $orderStatus = 'Preparing';
                    }elseif($val->in_transit == 'true'){
                        $orderStatus = 'In Transit';
                    }

                    $populateArray[] = [
                        'order_id' => $orderId,
                        'reference' =>  (int) $val->reference,
                        'reference_code' => $orderCode . $val->reference,
                        'customer_id' => $customerId,
                        'customer_name' => $orderData->customer_name,
                        'customer_avatar' => $customer::$publicDirectory . '/' . $customerData->customer_avatar,
                        'customer_address' => $orderData->customer_address ?? '',
                        'is_preparing' => $val->is_preparing == 'true' ? true : false,
                        'is_refunded' => $val->is_refunded == 'true' ? true : false,
                        'in_transit' => $val->in_transit == 'true' ? true : false,
                        'created_at' => Helper::timeAgo($val->created_at),
                        'order_table_no' => (int) $val->order_table_no,
                        'order_total' => (float) $val->order_total,
                        'order_currency' => $val->order_currency,
                        'order_type' => $val->order_type,
                        'order_status' => $orderStatus,
                        'order_note' => $val->order_note,
                    ];
                }
            endif;

            $dataArray = [
                'total_delivery' => (int) $orderStatistics->total_delivery,
                'total_takeaway' => (int) $orderStatistics->total_takeaway ?? 0,
                'total_dinein' => (int) $orderStatistics->total_dine_in ?? 0,
                'total_accepted' => (int) $orderStatistics->total_accepted ?? 0,
                'total_declined_refunded' => (int) $orderStatistics->total_declined_refunded ?? 0,
                'total_in_transit' => (int) $orderStatistics->total_in_transit ?? 0,
                'total_completed' => (int) $orderStatistics->total_completed ?? 0,
                'orders' => $populateArray,
            ];

            return ['status' => true, 'data' => $dataArray];
        }

        return ["status" => false, "message" => "Sorry, no action was provided."];
    }

    public function setStatus(array $data): array
    {
        $orderReference = $data['order_reference'] ?? null;
        $status = $data['order_status'] ?? '';
        $restaurantId = (int) $this->tokenData['id'];

        if(empty($orderReference) || empty($status)){
            return ['status' => false, 'message' => 'Sorry, order reference or order status was not provided.'];
        }

        if(empty($restaurantId)){
            return ['status' => false, 'message' => 'Sorry, restaurant data was not provided.'];
        }

        $orders = new Orders;
        $orderData = $orders->getByReference($orderReference, 'order_id, restaurant_id, order_type, order_status');
        if($orderData->restaurant_id != $restaurantId){
            return ['status' => false, 'message' => 'Sorry, this order was not found.'];
        }

        $orderId = (int) $orderData->order_id;
        if($orderData && \in_array($status, ['on-hold','accepted', 'declined', 'completed', 'pending'])){
            // update order status
            $orders->updateStatus($orderId, $status);
            if($status === 'accepted'){
                // update is_preparing if order type is dine-in
                if($orderData->order_type === 'dine-in'){
                    $orders->updateColumn('is_preparing', 'true', $orderId);
                }
            }

            if($status === 'completed'){
                // set is_preparing to false if order type is dine-in
                if($orderData->order_type === 'dine-in'){
                    $orders->updateColumn('is_preparing', 'false', $orderId);
                }

                // set in_transit to false if order type is delivery
                if($orderData->order_type === 'delivery'){
                    $orders->updateColumn('in_transit', 'false', $orderId);
                }
            }

            return ['status' => true, 'message' => 'Successfully updated.'];
        }

        return ['status' => false, 'message' => 'Sorry, no action was provided.'];
    }
}
