<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Orders extends CI_Controller {

	function __construct()
	{
		parent::__construct();
        $this->load->helper('url');
        $this->load->library('session');
		$this->load->model('common');
        $this->load->helper('delivery');
    }

    /**
     * List all orders with filters
     */
	public function index()
	{
        // Get all cities for filter dropdown
        $allCities = $this->common->readdatafromcollectionwhereclause('Cities');
        $data['cities'] = $allCities;
        
        // Get filter parameters
        $filterCity = $this->input->get('filter_city');
        $filterStatus = $this->input->get('filter_status');
        $filterFulfillment = $this->input->get('filter_fulfillment');
        $filterDateFrom = $this->input->get('filter_date_from');
        $filterDateTo = $this->input->get('filter_date_to');
        
        // Get all orders
        $allOrders = $this->common->readdatafromcollectionwhereclause('Orders');
        
        // Apply filters
        $filteredOrders = array();
        foreach ($allOrders as $orderId => $order) {
            // Filter by city
            if ($filterCity && (!isset($order['cityId']) || $order['cityId'] != $filterCity)) {
                continue;
            }
            
            // Filter by status
            if ($filterStatus && $filterStatus != 'all') {
                $orderStatus = isset($order['orderStatus']) ? $order['orderStatus'] : 'pending';
                
                // Special handling for blocked orders
                if ($filterStatus == 'blocked') {
                    // We'll check this after enhancing the data
                } else {
                    if ($orderStatus != $filterStatus) {
                        continue;
                    }
                }
            }
            
            // Filter by fulfillment type
            if ($filterFulfillment && $filterFulfillment != 'all') {
                $hasCannabusInventory = false;
                $hasStorefront = false;
                
                if (isset($order['items']) && is_array($order['items'])) {
                    foreach ($order['items'] as $item) {
                        if (isset($item['vendorId'])) {
                            $vendor = $this->common->readdatadocument('Users', $item['vendorId']);
                            if (!empty($vendor)) {
                                $fulfillmentType = isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'storefront_pickup';
                                if ($fulfillmentType == 'cannabus_inventory') {
                                    $hasCannabusInventory = true;
                                } else {
                                    $hasStorefront = true;
                                }
                            }
                        }
                    }
                }
                
                if ($filterFulfillment == 'cannabus_inventory' && !$hasCannabusInventory) {
                    continue;
                }
                if ($filterFulfillment == 'storefront_pickup' && !$hasStorefront) {
                    continue;
                }
            }
            
            // Filter by date range
            if ($filterDateFrom || $filterDateTo) {
                $orderDate = isset($order['date']) ? $order['date'] : 0;
                
                if ($filterDateFrom) {
                    $fromTimestamp = strtotime($filterDateFrom) * 1000;
                    if ($orderDate < $fromTimestamp) {
                        continue;
                    }
                }
                
                if ($filterDateTo) {
                    $toTimestamp = strtotime($filterDateTo . ' 23:59:59') * 1000;
                    if ($orderDate > $toTimestamp) {
                        continue;
                    }
                }
            }
            
            $filteredOrders[$orderId] = $order;
        }
        
        // Sort by date (newest first)
        usort($filteredOrders, function($a, $b) {
            $dateA = isset($a['date']) ? $a['date'] : 0;
            $dateB = isset($b['date']) ? $b['date'] : 0;
            return $dateB - $dateA;
        });
        
        // Enhance order data with city names and detect blocked orders
        $enhancedOrders = $this->enhanceOrderData($filteredOrders, $allCities);
        
        // Filter by blocked status if needed (after enhancement)
        if ($filterStatus == 'blocked') {
            $finalOrders = array();
            foreach ($enhancedOrders as $orderId => $order) {
                if (isset($order['isBlocked']) && $order['isBlocked']) {
                    $finalOrders[$orderId] = $order;
                }
            }
            $enhancedOrders = $finalOrders;
        }
        
        $data['orders'] = $enhancedOrders;
        $data['filterCity'] = $filterCity;
        $data['filterStatus'] = $filterStatus;
        $data['filterFulfillment'] = $filterFulfillment;
        $data['filterDateFrom'] = $filterDateFrom;
        $data['filterDateTo'] = $filterDateTo;
        
        $this->template->template_render('orders', $data);
    }
    
    /**
     * Enhance order data with city names and blocked status
     */
    private function enhanceOrderData($orders, $cities)
    {
        $this->load->helper('delivery');
        
        foreach ($orders as $orderId => &$order) {
            // Add city name
            if (isset($order['cityId']) && isset($cities[$order['cityId']])) {
                $order['cityName'] = isset($cities[$order['cityId']]['cityName']) ? $cities[$order['cityId']]['cityName'] : 'Unknown';
            } else {
                $order['cityName'] = 'Unknown';
            }
            
            // Categorize items by fulfillment type for list view
            $cannabusItems = array();
            $storefrontItems = array();
            if (isset($order['items']) && is_array($order['items'])) {
                foreach ($order['items'] as $item) {
                    if (isset($item['vendorId'])) {
                        $vendor = $this->common->readdatadocument('Users', $item['vendorId']);
                        if (!empty($vendor)) {
                            $fulfillmentType = isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'storefront_pickup';
                            if ($fulfillmentType == 'cannabus_inventory') {
                                $cannabusItems[] = $item;
                            } else {
                                $storefrontItems[] = $item;
                            }
                        }
                    }
                }
            }
            $order['cannabusItems'] = $cannabusItems;
            $order['storefrontItems'] = $storefrontItems;
            
            // Detect if order is blocked (minimum order not met)
            $order['isBlocked'] = false;
            $order['blockReason'] = '';
            
            if (isset($order['zone']) && isset($order['cityId'])) {
                $zones = get_city_zones($order['cityId'], $this->common);
                if (!empty($zones)) {
                    $zoneKey = $order['zone'];
                    $isStorefront = !empty($storefrontItems);
                    $zonePricing = get_zone_pricing($zoneKey, $zones, $isStorefront);
                    
                    $cartTotal = isset($order['cartTotal']) ? $order['cartTotal'] : 0;
                    $minimumOrder = isset($zonePricing['minimumOrder']) ? $zonePricing['minimumOrder'] : 0;
                    
                    if ($isStorefront && $zoneKey == 'zone2' && isset($zonePricing['storefrontMinimumOrder'])) {
                        $minimumOrder = $zonePricing['storefrontMinimumOrder'];
                    }
                    
                    if ($cartTotal < $minimumOrder) {
                        $order['isBlocked'] = true;
                        $order['blockReason'] = "Minimum order not met. Required: $" . number_format($minimumOrder, 2) . ", Current: $" . number_format($cartTotal, 2);
                    }
                }
            }
        }
        
        return $orders;
    }

    /**
     * View order details
     */
    public function view()
    {
        $orderId = $this->uri->segment(3);
        if (!$orderId) {
            redirect(base_url('orders'));
            return;
        }

        $order = $this->common->readdatadocument('Orders', $orderId);
        if (empty($order)) {
            $this->session->set_flashdata('warningmessage', 'Order not found');
            redirect(base_url('orders'));
            return;
        }

        $this->load->helper('delivery');

        // Get city data
        if (isset($order['cityId'])) {
            $data['city'] = $this->common->readdatadocument('Cities', $order['cityId']);
            
            // Get zone configuration
            if (!empty($data['city'])) {
                $data['zones'] = get_city_zones($order['cityId'], $this->common);
            }
        }

        // Get customer data
        if (isset($order['customerId'])) {
            $data['customer'] = $this->common->readdatadocument('Users', $order['customerId']);
        }

        // Enhance order items with vendor information
        if (isset($order['items']) && is_array($order['items'])) {
            $enhancedItems = array();
            $cannabusItems = array();
            $storefrontItems = array();
            
            foreach ($order['items'] as $item) {
                $itemData = $item;
                
                if (isset($item['vendorId'])) {
                    $vendor = $this->common->readdatadocument('Users', $item['vendorId']);
                    if (!empty($vendor)) {
                        $itemData['vendorName'] = isset($vendor['shopName']) ? $vendor['shopName'] : 
                            (isset($vendor['firstName']) ? $vendor['firstName'] . ' ' . (isset($vendor['lastName']) ? $vendor['lastName'] : '') : 'Unknown');
                        $itemData['vendorEmail'] = isset($vendor['email']) ? $vendor['email'] : '';
                        $itemData['fulfillmentType'] = isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'storefront_pickup';
                        
                        if ($itemData['fulfillmentType'] == 'cannabus_inventory') {
                            $cannabusItems[] = $itemData;
                        } else {
                            $storefrontItems[] = $itemData;
                        }
                    }
                }
                
                // Get product information if productId exists
                if (isset($item['productId'])) {
                    $product = $this->common->readdatadocument('Products', $item['productId']);
                    if (!empty($product)) {
                        $itemData['productName'] = isset($product['productName']) ? $product['productName'] : 'Unknown Product';
                        $itemData['productImage'] = isset($product['productUrl']) ? $product['productUrl'] : '';
                    }
                }
                
                $enhancedItems[] = $itemData;
            }
            
            $order['items'] = $enhancedItems;
            $order['cannabusItems'] = $cannabusItems;
            $order['storefrontItems'] = $storefrontItems;
            $order['hasMultipleVendors'] = count($storefrontItems) > 1;
        }

        // Detect blocked order
        $order['isBlocked'] = false;
        $order['blockReason'] = '';
        if (isset($order['zone']) && isset($order['cityId']) && !empty($data['zones'])) {
            $zoneKey = $order['zone'];
            $isStorefront = !empty($storefrontItems);
            $zonePricing = get_zone_pricing($zoneKey, $data['zones'], $isStorefront);
            
            $cartTotal = isset($order['cartTotal']) ? $order['cartTotal'] : 0;
            $minimumOrder = isset($zonePricing['minimumOrder']) ? $zonePricing['minimumOrder'] : 0;
            
            if ($isStorefront && $zoneKey == 'zone2' && isset($zonePricing['storefrontMinimumOrder'])) {
                $minimumOrder = $zonePricing['storefrontMinimumOrder'];
            }
            
            if ($cartTotal < $minimumOrder) {
                $order['isBlocked'] = true;
                $order['blockReason'] = "Minimum order not met. Required: $" . number_format($minimumOrder, 2) . ", Current: $" . number_format($cartTotal, 2);
            }
        }

        $data['order'] = $order;
        $data['orderId'] = $orderId;
        
        $this->template->template_render('order_view', $data);
    }

    /**
     * Update order status
     * When order is marked as completed, automatically process loyalty points
     */
    public function updatestatus()
    {
        $orderId = $this->input->post('orderId');
        $status = $this->input->post('status');

        if (!$orderId || !$status) {
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('success' => false, 'message' => 'Order ID and status are required'));
		} else {
                $this->session->set_flashdata('warningmessage', 'Order ID and status are required');
                redirect(base_url('orders'));
            }
            return;
        }

        // Get current order to check previous status
        $currentOrder = $this->common->readdatadocument('Orders', $orderId);
        $previousStatus = isset($currentOrder['orderStatus']) ? strtolower($currentOrder['orderStatus']) : '';

        $data = array('orderStatus' => $status);
        $response = $this->common->updatedatamodel('Orders', $orderId, $data);

		if ($response) {
            // If order is being marked as completed/delivered/rated, process loyalty points
            $statusLower = strtolower($status);
            $isCompleted = in_array($statusLower, array('completed', 'delivered', 'rated'));
            $wasNotCompleted = !in_array($previousStatus, array('completed', 'delivered', 'rated'));

            if ($isCompleted && $wasNotCompleted) {
                // Process loyalty points via API endpoint
                $this->processLoyaltyPointsForOrder($orderId);
            }

            if ($this->input->is_ajax_request()) {
                echo json_encode(array('success' => true, 'message' => 'Order status updated successfully'));
		} else {
                $this->session->set_flashdata('successmessage', 'Order status updated successfully');
                redirect(base_url('orders/view/' . $orderId));
            }
		} else {
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('success' => false, 'message' => 'Failed to update order status'));
            } else {
                $this->session->set_flashdata('warningmessage', 'Failed to update order status');
                redirect(base_url('orders/view/' . $orderId));
            }
        }
    }

    /**
     * Process loyalty points for a completed order
     * Uses direct method call (more efficient than HTTP request)
     * @param string $orderId Order ID
     * @return bool Success status
     */
    private function processLoyaltyPointsForOrder($orderId)
    {
        $this->load->helper('loyalty');
        
        // Get order
        $order = $this->common->readdatadocument('Orders', $orderId);
        if (empty($order)) {
            log_message('error', 'Loyalty: Order not found - ' . $orderId);
            return false;
        }
        
        // Check if already processed
        $transactions = $this->common->readdatafromcollectionwhereclause('LoyaltyTransactions');
        $alreadyProcessed = false;
        if (!empty($transactions)) {
            foreach ($transactions as $transaction) {
                if (isset($transaction['orderId']) && $transaction['orderId'] == $orderId && 
                    isset($transaction['type']) && $transaction['type'] == 'earned') {
                    $alreadyProcessed = true;
                    break;
                }
            }
        }
        
        if ($alreadyProcessed) {
            log_message('info', 'Loyalty: Points already processed for order - ' . $orderId);
            return false;
        }
        
        // Get customer ID
        $customerId = isset($order['customerId']) ? $order['customerId'] : (isset($order['userId']) ? $order['userId'] : null);
        if (!$customerId) {
            log_message('error', 'Loyalty: Customer ID not found in order - ' . $orderId);
            return false;
        }
        
        // Verify customer exists and is a customer
        $customer = $this->common->readdatadocument('Users', $customerId);
        if (empty($customer)) {
            log_message('error', 'Loyalty: Customer not found - ' . $customerId);
            return false;
        }
        
        $userRole = isset($customer['userRole']) ? $customer['userRole'] : '';
        if ($userRole != 'user') {
            log_message('info', 'Loyalty: User is not a customer - ' . $customerId);
            return false;
        }
        
        // Get order total
        $orderTotal = 0;
        if (isset($order['totalAmount'])) {
            $orderTotal = floatval($order['totalAmount']);
        } elseif (isset($order['price'])) {
            $orderTotal = floatval($order['price']);
        } elseif (isset($order['cartTotal']) && isset($order['deliveryFee'])) {
            $orderTotal = floatval($order['cartTotal']) + floatval($order['deliveryFee']);
        } elseif (isset($order['cartTotal'])) {
            $orderTotal = floatval($order['cartTotal']);
        }
        
        if ($orderTotal <= 0) {
            log_message('error', 'Loyalty: Invalid order total for order - ' . $orderId);
            return false;
        }
        
        // Check if loyalty is enabled
        $settings = get_loyalty_settings($this->common);
        if (empty($settings) || (isset($settings['loyaltyEnabled']) && !$settings['loyaltyEnabled'])) {
            log_message('info', 'Loyalty: Program is disabled');
            return false;
        }
        
        // Calculate loyalty points (determines applicable reward rules)
        $pointsCalculation = calculate_loyalty_points($orderTotal, $customerId, $orderId, $this->common);
        $pointsEarned = isset($pointsCalculation['points']) ? intval($pointsCalculation['points']) : 0;
        
        if ($pointsEarned <= 0) {
            log_message('info', 'Loyalty: No points to award for order - ' . $orderId);
            return false;
        }
        
        // Build description with breakdown
        $breakdown = isset($pointsCalculation['breakdown']) ? $pointsCalculation['breakdown'] : array();
        $description = 'Points earned from order #' . $orderId;
        if (!empty($breakdown)) {
            $bonusDescriptions = array();
            foreach ($breakdown as $bonus) {
                if (isset($bonus['description'])) {
                    $bonusDescriptions[] = $bonus['description'];
                }
            }
            if (!empty($bonusDescriptions)) {
                $description .= ' (' . implode(', ', $bonusDescriptions) . ')';
            }
        }
        
        // Award loyalty points (creates history record and updates tier)
        $awardResult = award_loyalty_points($customerId, $pointsEarned, 'earned', $orderId, $description, $this->common);
        
        if (!$awardResult) {
            log_message('error', 'Loyalty: Failed to award points for order - ' . $orderId);
            return false;
        }
        
        // Mark order as processed
        $updateData = array(
            'loyaltyPointsProcessed' => true,
            'loyaltyPointsEarned' => $pointsEarned,
            'loyaltyPointsProcessedAt' => time() * 1000
        );
        $this->common->updatedatamodel('Orders', $orderId, $updateData);
        
        log_message('info', 'Loyalty: Successfully processed ' . $pointsEarned . ' points for order - ' . $orderId);
        return true;
    }

    /**
     * Filter orders by status (legacy method - redirects to index with filter)
     */
    public function filter()
    {
        $status = $this->uri->segment(3);
        redirect(base_url('orders?filter_status=' . ($status ? $status : 'all')));
	}
}
