<?php
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

use Restserver\Libraries\REST_Controller;
defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH . 'libraries/REST_Controller.php';
require APPPATH . 'libraries/Format.php';
class Api extends REST_Controller {
    function __construct()
    {
        parent::__construct();

        $this->load->model('api_model');
        $this->load->model('geofence_model');
        $this->load->model('common');
        $this->load->helper('delivery');
        $this->load->helper('loyalty');

    }
    public function index_get() {
            //$this->checkgeofence('8','22.275334996986643','70.88614147123701');
    }

    public function index_post()   //Get GPS feed in device
    { 
       $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : ''; 
       $checklogin = $this->api_model->checkgps_auth($id);   

 
       if($checklogin) 
       { 
        echo $v_id = $checklogin[0]['v_id'];
        $lat = isset($_REQUEST["lat"]) ? $_REQUEST["lat"] : NULL;
        $lon = isset($_REQUEST["lon"]) ? $_REQUEST["lon"] : NULL;
        $timestamp = isset($_REQUEST["timestamp"]) ? $_REQUEST["timestamp"] : NULL;
        $altitude = isset($_REQUEST["altitude"]) ? $_REQUEST["altitude"] : NULL;
        $speed = isset($_REQUEST["speed"]) ? $_REQUEST["speed"] : NULL;
        $bearing = isset($_REQUEST["bearing"]) ? $_REQUEST["bearing"] : NULL;
        $accuracy = isset($_REQUEST["accuracy"]) ? $_REQUEST["accuracy"] : NULL;
        $comment = isset($_REQUEST["comment"]) ? $_REQUEST["comment"] : NULL;
        $postarray = array('v_id'=>$v_id,'latitude'=>$lat,'longitude'=>$lon,'time'=>date('Y-m-d h:i:s'),'altitude'=>$altitude,'speed'=>$speed,'bearing'=>$bearing,'accuracy'=>$accuracy,'comment'=>$comment);
        $this->api_model->add_postion($postarray);
        $this->checkgeofence($v_id,$lat,$lon);
        $response = array('error'=>false,'message'=>['v_id' => $v_id]);
        $this->set_response($response);
       } 
       
    }
    public function positions_post()     //Postion feed to front end   
    {
        $this->db->select("*");
        $this->db->from('positions');
        $this->db->where('v_id',$this->post('t_vechicle'));
        $this->db->where('date(time) >=', $this->post('fromdate'));
        $this->db->where('date(time) <=', $this->post('todate'));
        $query = $this->db->get();
        $data = $query->result_array();
        $distancefrom = reset($data);
        $distanceto = end($data);
        $totaldist = $this->totaldistance($distancefrom,$distanceto);
        $returndata = array('status'=>1,'data'=>$data,'totaldist'=>$totaldist,'message'=>'data');
        $this->set_response($returndata);
    }

    public function totaldistance($distancefrom,$distanceto,$earthRadius = 6371000)
    {
        $latFrom = deg2rad($distancefrom['latitude']);
        $lonFrom = deg2rad($distancefrom['longitude']);
        $latTo = deg2rad($distanceto['latitude']);
        $lonTo = deg2rad($distanceto['longitude']);
        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;
        $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
        return $angle * $earthRadius;
    }
    public function currentpositions_get()     
    { 
        $data = array();
        $postions = array();
        $this->db->select("p.*,v.v_name,v.v_type,v.v_color");
        $this->db->from('positions p');
        $this->db->join('vehicles v', 'v.v_id = p.v_id');
        $this->db->where('v.v_is_active', 1);
        
        if(isset($_GET['uname'])) { $this->db->where('v.v_api_username',$_GET['uname']);  }

        if(isset($_GET['gr'])) { $this->db->where('v.v_group',$_GET['gr']);  }

        if(isset($_GET['v_id'])) { $this->db->where('v.v_id',$_GET['v_id']);  }

        $this->db->where('`id` IN (SELECT MAX(id) FROM positions GROUP BY `v_id`)', NULL, FALSE);
        $query = $this->db->get();
        $data = $query->result_array();
        if(count($data)>=1) {
            $resp = array('status'=>1,'data'=>$data);
        } else {
            $resp = array('status'=>0,'message'=>'No live GPS feed found');
        }
        $this->set_response($resp);
    }
    public function checkgeofence($vid,$lat,$log)     
    { 
        $vgeofence = $this->geofence_model->getvechicle_geofence($vid);
        if(!empty($vgeofence)) {
            $points = array("$lat $log");
            foreach($vgeofence as $geofencedata) {
                $lastgeo = explode(" ,",$geofencedata['geo_area']);
                $polygon = $geofencedata['geo_area'].$lastgeo[0];
                $polygondata = explode(' , ',$polygon);
                foreach($polygondata as $polygoncln) {
                    $geopolygondata[] = str_replace("," , ' ',$polygoncln); 
                }
                foreach($points as $key => $point) {
                    $geocheck = pointInPolygon($point, $geopolygondata,false);
                    if($geocheck=='outside' || $geocheck=='boundary' || $geocheck=='inside') {
                        $wharray = array('ge_v_id' => $vid, 'ge_geo_id' => $geofencedata['geo_id'], 'ge_event' => $geocheck,
                            'DATE(ge_timestamp)'=>date('Y-m-d'));
                        $geofence_events = $this->db->select('*')->from('geofence_events')->where($wharray)->get()->result_array();
                       
                        if(count($geofence_events)==0) {
                            $insertarray = array('ge_v_id'=>$vid,'ge_geo_id'=>$geofencedata['geo_id'],'ge_event'=>$geocheck,'ge_timestamp'=>
                                       date('Y-m-d h:i:s'));
                            $this->db->insert('geofence_events',$insertarray);
                        } 
                    }
                }
            }
        }
    }

    /**
     * Checkout API - Calculate delivery fee and validate minimum order
     * POST /api/checkout
     * 
     * Required parameters:
     * - cityId: City ID
     * - customerLat: Customer latitude
     * - customerLon: Customer longitude
     * - items: Array of order items with vendorId and quantity
     * - cartTotal: Total cart value
     */
    public function checkout_post()
    {
        $cityId = $this->post('cityId');
        $customerLat = floatval($this->post('customerLat'));
        $customerLon = floatval($this->post('customerLon'));
        $items = $this->post('items'); // Array of {vendorId, productId, quantity, price}
        $cartTotal = floatval($this->post('cartTotal'));

        // Validate required fields
        if (!$cityId || !$customerLat || !$customerLon || empty($items) || !$cartTotal) {
            $this->response(array(
                'success' => false,
                'message' => 'Missing required fields: cityId, customerLat, customerLon, items, cartTotal'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get city data
        $city = $this->common->readdatadocument('Cities', $cityId);
        if (empty($city) || !isset($city['hqLatitude']) || !isset($city['hqLongitude'])) {
            $this->response(array(
                'success' => false,
                'message' => 'City not found or HQ not configured'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Prepare customer data
        $customer = array(
            'latitude' => $customerLat,
            'longitude' => $customerLon
        );

        // Prepare order items with vendor data
        $orderItems = array();
        $hasStorefront = false;
        
        foreach ($items as $item) {
            if (!isset($item['vendorId'])) {
                continue;
            }
            
            // Vendors are stored in Users collection with userRole == 'vendor'
            $vendor = $this->common->readdatadocument('Users', $item['vendorId']);
            if (empty($vendor) || !isset($vendor['userRole']) || $vendor['userRole'] != 'vendor') {
                continue;
            }
            
            $orderItems[] = array(
                'vendor' => $vendor,
                'vendorId' => $item['vendorId'],
                'productId' => isset($item['productId']) ? $item['productId'] : '',
                'quantity' => isset($item['quantity']) ? intval($item['quantity']) : 1,
                'price' => isset($item['price']) ? floatval($item['price']) : 0
            );
            
            if (isset($vendor['fulfillment_type']) && $vendor['fulfillment_type'] == 'storefront_pickup') {
                $hasStorefront = true;
            }
        }

        if (empty($orderItems)) {
            $this->response(array(
                'success' => false,
                'message' => 'No valid order items found'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Calculate chargeable distance
        $chargeableDistance = calculate_chargeable_distance($orderItems, $city, $customer, $this->common);

        // Get zones configuration
        $zones = get_city_zones($cityId, $this->common);

        // Assign zone
        $zoneKey = assign_zone($chargeableDistance, $zones);

        // Get pricing
        $pricing = get_zone_pricing($zoneKey, $zones, $hasStorefront);

        // Check minimum order
        $minimumMet = $cartTotal >= $pricing['minimumOrder'];
        
        $response = array(
            'success' => true,
            'data' => array(
                'chargeableDistance' => round($chargeableDistance, 2),
                'zone' => $zoneKey,
                'deliveryFee' => $pricing['fee'],
                'minimumOrder' => $pricing['minimumOrder'],
                'cartTotal' => $cartTotal,
                'minimumMet' => $minimumMet,
                'canCheckout' => $minimumMet,
                'totalAmount' => $cartTotal + $pricing['fee']
            )
        );

        if (!$minimumMet) {
            $response['message'] = 'Minimum order of $' . $pricing['minimumOrder'] . ' required for this zone. Current cart: $' . $cartTotal;
        }

        $this->response($response, REST_Controller::HTTP_OK);
    }

    /**
     * Determine city from customer coordinates
     * Finds the nearest city based on distance calculation
     * @param float $customerLat Customer latitude
     * @param float $customerLon Customer longitude
     * @param float $maxDistance Maximum distance in miles (default: 50)
     * @return array|null City data or null if not found
     */
    private function determine_city_from_location($customerLat, $customerLon, $maxDistance = 50)
    {
        // Get all cities
        $allCities = $this->common->readdatafromcollectionwhereclause('Cities');
        
        if (empty($allCities)) {
            return null;
        }
        
        $nearestCity = null;
        $minDistance = PHP_FLOAT_MAX;
        
        // Load delivery helper for distance calculation
        $this->load->helper('delivery');
        
        foreach ($allCities as $cityId => $city) {
            // Use HQ coordinates if available, otherwise use city coordinates
            $cityLat = isset($city['hqLatitude']) ? $city['hqLatitude'] : 
                      (isset($city['latitude']) ? $city['latitude'] : null);
            $cityLon = isset($city['hqLongitude']) ? $city['hqLongitude'] : 
                      (isset($city['longitude']) ? $city['longitude'] : null);
            
            if (!$cityLat || !$cityLon) {
                continue;
            }
            
            // Calculate distance using Google Maps API (road distance)
            $distance = calculate_distance($customerLat, $customerLon, $cityLat, $cityLon);
            
            // Find the nearest city within the specified delivery range
            if ($distance < $minDistance && $distance <= $maxDistance) {
                $minDistance = $distance;
                $nearestCity = $city;
                $nearestCity['cityId'] = $cityId;
                $nearestCity['distance'] = $distance;
            }
        }
        
        return $nearestCity;
    }

    /**
     * Auto Calculate Price API - Automatically determines city and calculates prices
     * POST /api/autocalculateprice
     * 
     * Required parameters:
     * - customerLat: Customer latitude
     * - customerLon: Customer longitude
     * - products: Array of products with productId and quantity
     *   Example: [{"productId": "prod123", "quantity": 2}, {"productId": "prod456", "quantity": 1}]
     * 
     * Optional parameters:
     * - maxDistance: Maximum distance in miles to consider a city (default: 50)
     */
    public function autocalculateprice_post()
    {
        $customerLat = floatval($this->post('customerLat'));
        $customerLon = floatval($this->post('customerLon'));
        $products = $this->post('products'); // Array of {productId, quantity}
        $maxDistance = floatval($this->post('maxDistance')) ?: 50; // Default 50 miles

        // Validate required fields
        if (!$customerLat || !$customerLon || empty($products)) {
            $this->response(array(
                'success' => false,
                'message' => 'Missing required fields: customerLat, customerLon, products'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Determine city from location
        $city = $this->determine_city_from_location($customerLat, $customerLon, $maxDistance);
        
        if (empty($city)) {
            $this->response(array(
                'success' => false,
                'message' => 'No city found within delivery range. Please check your location or contact support.'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        $cityId = $city['cityId'];

        // Check if city HQ is configured
        if (!isset($city['hqLatitude']) || !isset($city['hqLongitude'])) {
            $this->response(array(
                'success' => false,
                'message' => 'City HQ not configured. Please contact support.',
                'detectedCity' => array(
                    'cityId' => $cityId,
                    'cityName' => isset($city['cityName']) ? $city['cityName'] : 'Unknown'
                )
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Prepare customer data
        $customer = array(
            'latitude' => $customerLat,
            'longitude' => $customerLon
        );

        // Process products and calculate prices (reuse logic from calculateprice_post)
        $orderItems = array();
        $productDetails = array();
        $cartTotal = 0;
        $hasStorefront = false;
        $invalidProducts = array();

        foreach ($products as $productRequest) {
            if (!isset($productRequest['productId']) || !isset($productRequest['quantity'])) {
                continue;
            }

            $productId = $productRequest['productId'];
            $quantity = intval($productRequest['quantity']);

            if ($quantity <= 0) {
                continue;
            }

            // Get product details
            $product = $this->common->readdatadocument('Products', $productId);
            if (empty($product)) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'reason' => 'Product not found'
                );
                continue;
            }

            // Get vendor for this product
            $vendorId = isset($product['userId']) ? $product['userId'] : null;
            if (!$vendorId) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Product has no vendor assigned'
                );
                continue;
            }

            // Get vendor details
            $vendor = $this->common->readdatadocument('Users', $vendorId);
            if (empty($vendor) || !isset($vendor['userRole']) || $vendor['userRole'] != 'vendor') {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Vendor not found or invalid'
                );
                continue;
            }

            // Get product price (use displayPrice if available, otherwise productPrice)
            $productPrice = isset($product['displayPrice']) ? floatval($product['displayPrice']) : 
                           (isset($product['productPrice']) ? floatval($product['productPrice']) : 0);
            
            if ($productPrice <= 0) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Product price is invalid'
                );
                continue;
            }

            // Calculate item total
            $itemTotal = $productPrice * $quantity;
            $cartTotal += $itemTotal;

            // Add to order items for distance calculation
            $orderItems[] = array(
                'vendor' => $vendor,
                'vendorId' => $vendorId,
                'productId' => $productId,
                'quantity' => $quantity,
                'price' => $productPrice
            );

            // Track fulfillment type
            if (isset($vendor['fulfillment_type']) && $vendor['fulfillment_type'] == 'storefront_pickup') {
                $hasStorefront = true;
            }

            // Store product details for response
            $productDetails[] = array(
                'productId' => $productId,
                'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                'productImage' => isset($product['productUrl']) ? $product['productUrl'] : '',
                'vendorId' => $vendorId,
                'vendorName' => isset($vendor['shopName']) ? $vendor['shopName'] : 
                               (isset($vendor['firstName']) ? $vendor['firstName'] . ' ' . (isset($vendor['lastName']) ? $vendor['lastName'] : '') : 'Unknown'),
                'fulfillmentType' => isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'cannabus_inventory',
                'quantity' => $quantity,
                'unitPrice' => $productPrice,
                'itemTotal' => $itemTotal
            );
        }

        if (empty($orderItems)) {
            $this->response(array(
                'success' => false,
                'message' => 'No valid products found',
                'invalidProducts' => $invalidProducts,
                'detectedCity' => array(
                    'cityId' => $cityId,
                    'cityName' => isset($city['cityName']) ? $city['cityName'] : 'Unknown',
                    'distance' => isset($city['distance']) ? round($city['distance'], 2) : 0
                )
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Calculate chargeable distance using Google Maps API
        $chargeableDistance = calculate_chargeable_distance($orderItems, $city, $customer, $this->common);

        // Get zones configuration
        $zones = get_city_zones($cityId, $this->common);

        // Assign zone
        $zoneKey = assign_zone($chargeableDistance, $zones);

        // Get pricing
        $pricing = get_zone_pricing($zoneKey, $zones, $hasStorefront);

        // Check minimum order
        $minimumMet = $cartTotal >= $pricing['minimumOrder'];
        $deliveryFee = $pricing['fee'];
        $totalAmount = $cartTotal + $deliveryFee;

        // Build response
        $response = array(
            'success' => true,
            'data' => array(
                'detectedCity' => array(
                    'cityId' => $cityId,
                    'cityName' => isset($city['cityName']) ? $city['cityName'] : 'Unknown',
                    'state' => isset($city['state']) ? $city['state'] : '',
                    'country' => isset($city['country']) ? $city['country'] : '',
                    'distanceFromCity' => isset($city['distance']) ? round($city['distance'], 2) : 0
                ),
                'products' => $productDetails,
                'pricing' => array(
                    'subtotal' => round($cartTotal, 2),
                    'deliveryFee' => round($deliveryFee, 2),
                    'total' => round($totalAmount, 2)
                ),
                'delivery' => array(
                    'chargeableDistance' => round($chargeableDistance, 2),
                    'zone' => $zoneKey,
                    'minimumOrder' => $pricing['minimumOrder'],
                    'minimumMet' => $minimumMet
                ),
                'summary' => array(
                    'totalItems' => count($productDetails),
                    'totalQuantity' => array_sum(array_column($productDetails, 'quantity')),
                    'cartTotal' => round($cartTotal, 2),
                    'deliveryFee' => round($deliveryFee, 2),
                    'totalAmount' => round($totalAmount, 2),
                    'canCheckout' => $minimumMet
                )
            )
        );

        if (!empty($invalidProducts)) {
            $response['warnings'] = array(
                'invalidProducts' => $invalidProducts,
                'message' => 'Some products could not be processed'
            );
        }

        if (!$minimumMet) {
            $response['message'] = 'Minimum order of $' . number_format($pricing['minimumOrder'], 2) . 
                                  ' required for this zone. Current cart: $' . number_format($cartTotal, 2);
        }

        $this->response($response, REST_Controller::HTTP_OK);
    }

    /**
     * Calculate Price API - Calculate prices for products based on location
     * POST /api/calculateprice
     * 
     * Required parameters:
     * - cityId: City ID
     * - customerLat: Customer latitude
     * - customerLon: Customer longitude
     * - products: Array of products with productId and quantity
     *   Example: [{"productId": "prod123", "quantity": 2}, {"productId": "prod456", "quantity": 1}]
     */
    public function calculateprice_post()
    {
        $cityId = $this->post('cityId');
        $customerLat = floatval($this->post('customerLat'));
        $customerLon = floatval($this->post('customerLon'));
        $products = $this->post('products'); // Array of {productId, quantity}

        // Validate required fields
        if (!$cityId || !$customerLat || !$customerLon || empty($products)) {
            $this->response(array(
                'success' => false,
                'message' => 'Missing required fields: cityId, customerLat, customerLon, products'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get city data
        $city = $this->common->readdatadocument('Cities', $cityId);
        if (empty($city) || !isset($city['hqLatitude']) || !isset($city['hqLongitude'])) {
            $this->response(array(
                'success' => false,
                'message' => 'City not found or HQ not configured'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Prepare customer data
        $customer = array(
            'latitude' => $customerLat,
            'longitude' => $customerLon
        );

        // Process products and calculate prices
        $orderItems = array();
        $productDetails = array();
        $cartTotal = 0;
        $hasStorefront = false;
        $invalidProducts = array();

        foreach ($products as $productRequest) {
            if (!isset($productRequest['productId']) || !isset($productRequest['quantity'])) {
                continue;
            }

            $productId = $productRequest['productId'];
            $quantity = intval($productRequest['quantity']);

            if ($quantity <= 0) {
                continue;
            }

            // Get product details
            $product = $this->common->readdatadocument('Products', $productId);
            if (empty($product)) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'reason' => 'Product not found'
                );
                continue;
            }

            // Get vendor for this product
            $vendorId = isset($product['userId']) ? $product['userId'] : null;
            if (!$vendorId) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Product has no vendor assigned'
                );
                continue;
            }

            // Get vendor details
            $vendor = $this->common->readdatadocument('Users', $vendorId);
            if (empty($vendor) || !isset($vendor['userRole']) || $vendor['userRole'] != 'vendor') {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Vendor not found or invalid'
                );
                continue;
            }

            // Get product price (use displayPrice if available, otherwise productPrice)
            $productPrice = isset($product['displayPrice']) ? floatval($product['displayPrice']) : 
                           (isset($product['productPrice']) ? floatval($product['productPrice']) : 0);
            
            if ($productPrice <= 0) {
                $invalidProducts[] = array(
                    'productId' => $productId,
                    'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                    'reason' => 'Product price is invalid'
                );
                continue;
            }

            // Calculate item total
            $itemTotal = $productPrice * $quantity;
            $cartTotal += $itemTotal;

            // Add to order items for distance calculation
            $orderItems[] = array(
                'vendor' => $vendor,
                'vendorId' => $vendorId,
                'productId' => $productId,
                'quantity' => $quantity,
                'price' => $productPrice
            );

            // Track fulfillment type
            if (isset($vendor['fulfillment_type']) && $vendor['fulfillment_type'] == 'storefront_pickup') {
                $hasStorefront = true;
            }

            // Store product details for response
            $productDetails[] = array(
                'productId' => $productId,
                'productName' => isset($product['productName']) ? $product['productName'] : 'Unknown',
                'productImage' => isset($product['productUrl']) ? $product['productUrl'] : '',
                'vendorId' => $vendorId,
                'vendorName' => isset($vendor['shopName']) ? $vendor['shopName'] : 
                               (isset($vendor['firstName']) ? $vendor['firstName'] . ' ' . (isset($vendor['lastName']) ? $vendor['lastName'] : '') : 'Unknown'),
                'fulfillmentType' => isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'cannabus_inventory',
                'quantity' => $quantity,
                'unitPrice' => $productPrice,
                'itemTotal' => $itemTotal
            );
        }

        if (empty($orderItems)) {
            $this->response(array(
                'success' => false,
                'message' => 'No valid products found',
                'invalidProducts' => $invalidProducts
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Calculate chargeable distance using Google Maps API
        $chargeableDistance = calculate_chargeable_distance($orderItems, $city, $customer, $this->common);
        
        // Calculate detailed distance breakdown for multiple vendors
        $distanceBreakdown = array();
        $hqLat = isset($city['hqLatitude']) ? $city['hqLatitude'] : null;
        $hqLon = isset($city['hqLongitude']) ? $city['hqLongitude'] : null;
        $customerLat = $customer['latitude'];
        $customerLon = $customer['longitude'];
        
        // Group products by vendor and fulfillment type
        $vendorGroups = array();
        foreach ($orderItems as $item) {
            $vendor = $item['vendor'];
            $vendorId = $item['vendorId'];
            $fulfillmentType = isset($vendor['fulfillment_type']) ? $vendor['fulfillment_type'] : 'cannabus_inventory';
            
            if (!isset($vendorGroups[$vendorId])) {
                $vendorGroups[$vendorId] = array(
                    'vendor' => $vendor,
                    'vendorId' => $vendorId,
                    'vendorName' => isset($vendor['shopName']) ? $vendor['shopName'] : 
                                   (isset($vendor['firstName']) ? $vendor['firstName'] . ' ' . (isset($vendor['lastName']) ? $vendor['lastName'] : '') : 'Unknown'),
                    'fulfillmentType' => $fulfillmentType,
                    'items' => array()
                );
            }
            $vendorGroups[$vendorId]['items'][] = $item;
        }
        
        // Calculate distance for each vendor group
        foreach ($vendorGroups as $vendorId => $vendorGroup) {
            $vendor = $vendorGroup['vendor'];
            $fulfillmentType = $vendorGroup['fulfillmentType'];
            
            if ($fulfillmentType == 'cannabus_inventory') {
                // Cannabus inventory: HQ → Customer
                $distance = calculate_distance($hqLat, $hqLon, $customerLat, $customerLon);
                $distanceBreakdown[] = array(
                    'vendorId' => $vendorId,
                    'vendorName' => $vendorGroup['vendorName'],
                    'fulfillmentType' => 'cannabus_inventory',
                    'route' => 'HQ → Customer',
                    'distance' => round($distance, 2)
                );
            } elseif ($fulfillmentType == 'storefront_pickup') {
                // Storefront: HQ → Vendor → Customer
                $vendorLat = isset($vendor['latitude']) ? floatval($vendor['latitude']) : null;
                $vendorLon = isset($vendor['longitude']) ? floatval($vendor['longitude']) : null;
                
                if ($vendorLat && $vendorLon && 
                    $vendorLat >= -90 && $vendorLat <= 90 && 
                    $vendorLon >= -180 && $vendorLon <= 180) {
                    
                    $hqToVendor = calculate_distance($hqLat, $hqLon, $vendorLat, $vendorLon);
                    $vendorToCustomer = calculate_distance($vendorLat, $vendorLon, $customerLat, $customerLon);
                    $totalDistance = $hqToVendor + $vendorToCustomer;
                    
                    $distanceBreakdown[] = array(
                        'vendorId' => $vendorId,
                        'vendorName' => $vendorGroup['vendorName'],
                        'fulfillmentType' => 'storefront_pickup',
                        'route' => 'HQ → Vendor → Customer',
                        'hqToVendor' => round($hqToVendor, 2),
                        'vendorToCustomer' => round($vendorToCustomer, 2),
                        'distance' => round($totalDistance, 2)
                    );
                }
            }
        }

        // Get zones configuration
        $zones = get_city_zones($cityId, $this->common);

        // Assign zone
        $zoneKey = assign_zone($chargeableDistance, $zones);

        // Get pricing
        $pricing = get_zone_pricing($zoneKey, $zones, $hasStorefront);

        // Check minimum order
        $minimumMet = $cartTotal >= $pricing['minimumOrder'];
        $deliveryFee = $pricing['fee'];
        $totalAmount = $cartTotal + $deliveryFee;

        // Build response
        $response = array(
            'success' => true,
            'data' => array(
                'products' => $productDetails,
                'pricing' => array(
                    'subtotal' => round($cartTotal, 2),
                    'deliveryFee' => round($deliveryFee, 2),
                    'total' => round($totalAmount, 2)
                ),
                'delivery' => array(
                    'chargeableDistance' => round($chargeableDistance, 2),
                    'zone' => $zoneKey,
                    'minimumOrder' => $pricing['minimumOrder'],
                    'minimumMet' => $minimumMet,
                    'distanceBreakdown' => $distanceBreakdown,
                    'vendorCount' => count($vendorGroups),
                    'hasMultipleVendors' => count($vendorGroups) > 1,
                    'hasMixedFulfillment' => $hasStorefront && count($vendorGroups) > 1
                ),
                'summary' => array(
                    'totalItems' => count($productDetails),
                    'totalQuantity' => array_sum(array_column($productDetails, 'quantity')),
                    'cartTotal' => round($cartTotal, 2),
                    'deliveryFee' => round($deliveryFee, 2),
                    'totalAmount' => round($totalAmount, 2),
                    'canCheckout' => $minimumMet
                )
            )
        );

        if (!empty($invalidProducts)) {
            $response['warnings'] = array(
                'invalidProducts' => $invalidProducts,
                'message' => 'Some products could not be processed'
            );
        }

        if (!$minimumMet) {
            $response['message'] = 'Minimum order of $' . number_format($pricing['minimumOrder'], 2) . 
                                  ' required for this zone. Current cart: $' . number_format($cartTotal, 2);
        }

        $this->response($response, REST_Controller::HTTP_OK);
    }

    /**
     * Create Order API
     * POST /api/order
     * 
     * Required parameters:
     * - cityId: City ID
     * - customerId: Customer ID
     * - customerLat: Customer latitude
     * - customerLon: Customer longitude
     * - customerAddress: Customer delivery address
     * - items: Array of order items
     * - cartTotal: Total cart value
     * - deliveryFee: Delivery fee
     * - totalAmount: Total amount including delivery
     * - paymentMethod: Payment method
     * - paymentData: Payment data (optional)
     */
    public function order_post()
    {
        $cityId = $this->post('cityId');
        $customerId = $this->post('customerId');
        $customerLat = floatval($this->post('customerLat'));
        $customerLon = floatval($this->post('customerLon'));
        $customerAddress = $this->post('customerAddress');
        $items = $this->post('items');
        $cartTotal = floatval($this->post('cartTotal'));
        $deliveryFee = floatval($this->post('deliveryFee'));
        $totalAmount = floatval($this->post('totalAmount'));
        $paymentMethod = $this->post('paymentMethod');
        $paymentData = $this->post('paymentData');

        // Validate required fields
        if (!$cityId || !$customerId || !$customerLat || !$customerLon || !$customerAddress || 
            empty($items) || !$cartTotal || !$deliveryFee || !$totalAmount || !$paymentMethod) {
            $this->response(array(
                'success' => false,
                'message' => 'Missing required fields'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get city data
        $city = $this->common->readdatadocument('Cities', $cityId);
        if (empty($city)) {
            $this->response(array(
                'success' => false,
                'message' => 'City not found'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Calculate distance for order record
        $customer = array(
            'latitude' => $customerLat,
            'longitude' => $customerLon
        );
        
        $orderItems = array();
        foreach ($items as $item) {
            if (isset($item['vendorId'])) {
                // Vendors are stored in Users collection with userRole == 'vendor'
                $vendor = $this->common->readdatadocument('Users', $item['vendorId']);
                if (!empty($vendor) && isset($vendor['userRole']) && $vendor['userRole'] == 'vendor') {
                    $orderItems[] = array('vendor' => $vendor, 'vendorId' => $item['vendorId']);
                }
            }
        }
        
        $chargeableDistance = calculate_chargeable_distance($orderItems, $city, $customer, $this->common);
        $zones = get_city_zones($cityId, $this->common);
        $zoneKey = assign_zone($chargeableDistance, $zones);

        // Create order data
        $orderData = array(
            'cityId' => $cityId,
            'customerId' => $customerId,
            'customerLatitude' => $customerLat,
            'customerLongitude' => $customerLon,
            'customerAddress' => $customerAddress,
            'items' => $items,
            'cartTotal' => $cartTotal,
            'deliveryFee' => $deliveryFee,
            'totalAmount' => $totalAmount,
            'chargeableDistance' => $chargeableDistance,
            'zone' => $zoneKey,
            'paymentMethod' => $paymentMethod,
            'paymentData' => $paymentData,
            'orderStatus' => 'pending',
            'date' => time() * 1000, // Milliseconds timestamp
            'createdAt' => time() * 1000
        );

        // Save order to Firebase
        $orderId = time();
        $response = $this->common->adddatamodel('Orders', $orderId, $orderData);

        if ($response) {
            $this->response(array(
                'success' => true,
                'message' => 'Order created successfully',
                'data' => array(
                    'orderId' => $orderId,
                    'orderNumber' => 'ORD-' . $orderId,
                    'totalAmount' => $totalAmount,
                    'deliveryFee' => $deliveryFee,
                    'zone' => $zoneKey,
                    'estimatedDelivery' => date('Y-m-d H:i:s', time() + 3600) // 1 hour estimate
                )
            ), REST_Controller::HTTP_CREATED);
        } else {
            $this->response(array(
                'success' => false,
                'message' => 'Failed to create order'
            ), REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * Get Order Details
     * GET /api/order/{orderId}
     */
    public function order_get($orderId = null)
    {
        if (!$orderId) {
            $this->response(array(
                'success' => false,
                'message' => 'Order ID required'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        $order = $this->common->readdatadocument('Orders', $orderId);
        
        if (empty($order)) {
            $this->response(array(
                'success' => false,
                'message' => 'Order not found'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        $this->response(array(
            'success' => true,
            'data' => $order
        ), REST_Controller::HTTP_OK);
    }

    /**
     * Get Orders by Customer
     * GET /api/orders/customer/{customerId}
     */
    public function orders_customer_get($customerId = null)
    {
        if (!$customerId) {
            $this->response(array(
                'success' => false,
                'message' => 'Customer ID required'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        $orders = $this->common->readdatafromcollectionwhereclause('Orders', 'customerId', '=', $customerId);
        
        $this->response(array(
            'success' => true,
            'data' => $orders,
            'count' => count($orders)
        ), REST_Controller::HTTP_OK);
    }

    /**
     * Process Loyalty Points API - Award loyalty points when order is completed
     * POST /api/processLoyaltyPoints
     * 
     * Required parameters:
     * - orderId: Order ID
     * 
     * This endpoint:
     * 1. Retrieves the order
     * 2. Checks if loyalty points were already processed (prevents duplicates)
     * 3. Determines applicable reward rules using loyalty controller logic
     * 4. Calculates points based on order price
     * 5. Awards points to customer
     * 6. Updates customer tier/level
     * 7. Creates loyalty history record
     */
    public function processLoyaltyPoints_post()
    {
        $orderId = $this->post('orderId');

        // Validate required fields
        if (!$orderId) {
            $this->response(array(
                'success' => false,
                'message' => 'Order ID is required'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get order data
        $order = $this->common->readdatadocument('Orders', $orderId);
        if (empty($order)) {
            $this->response(array(
                'success' => false,
                'message' => 'Order not found'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Check if order is completed
        $orderStatus = isset($order['orderStatus']) ? strtolower($order['orderStatus']) : '';
        if (!in_array($orderStatus, array('completed', 'delivered', 'rated','deliver','rate','complete'))) {
            $this->response(array(
                'success' => false,
                'message' => 'Order is not completed. Only completed orders can earn loyalty points.',
                'currentStatus' => $orderStatus
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get customer ID
        $customerId = isset($order['customerId']) ? $order['customerId'] : (isset($order['userId']) ? $order['userId'] : null);
        if (!$customerId) {
            $this->response(array(
                'success' => false,
                'message' => 'Customer ID not found in order'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Verify customer exists and is a customer (not vendor/driver)
        $customer = $this->common->readdatadocument('Users', $customerId);
        if (empty($customer)) {
            $this->response(array(
                'success' => false,
                'message' => 'Customer not found'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Check if customer is actually a customer
        $userRole = isset($customer['userRole']) ? $customer['userRole'] : '';
        if ($userRole != 'user') {
            $this->response(array(
                'success' => false,
                'message' => 'User is not a customer. Only customers can earn loyalty points.'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Check if loyalty points were already processed for this order
        if ($this->isLoyaltyPointsProcessed($orderId)) {
            $this->response(array(
                'success' => false,
                'message' => 'Loyalty points have already been processed for this order',
                'orderId' => $orderId
            ), REST_Controller::HTTP_CONFLICT);
            return;
        }

        // Get order total (use totalAmount, price, or cartTotal + deliveryFee)
        $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) {
            $this->response(array(
                'success' => false,
                'message' => 'Invalid order total. Cannot calculate loyalty points for zero or negative amounts.'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get loyalty settings to check if loyalty is enabled
        $settings = get_loyalty_settings($this->common);
        if (empty($settings) || (isset($settings['loyaltyEnabled']) && !$settings['loyaltyEnabled'])) {
            $this->response(array(
                'success' => false,
                'message' => 'Loyalty program is disabled'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Calculate loyalty points using helper function
        // This function determines applicable reward rules (double points days, VIP promotions, tier bonuses)
        $pointsCalculation = calculate_loyalty_points($orderTotal, $customerId, $orderId, $this->common);
        
        $pointsEarned = isset($pointsCalculation['points']) ? intval($pointsCalculation['points']) : 0;
        $basePoints = isset($pointsCalculation['basePoints']) ? floatval($pointsCalculation['basePoints']) : 0;
        $multiplier = isset($pointsCalculation['multiplier']) ? floatval($pointsCalculation['multiplier']) : 1.0;
        $breakdown = isset($pointsCalculation['breakdown']) ? $pointsCalculation['breakdown'] : array();

        if ($pointsEarned <= 0) {
            $this->response(array(
                'success' => false,
                'message' => 'No points to award for this order',
                'orderTotal' => $orderTotal,
                'calculation' => $pointsCalculation
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get customer's current points and tier before awarding
        $currentPoints = isset($customer['points']) ? intval($customer['points']) : 0;
        $oldTier = get_customer_tier_from_points($currentPoints, $this->common);

        // Award loyalty points (this also creates the loyalty history record)
        $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) . ')';
            }
        }

        $awardResult = award_loyalty_points(
            $customerId,
            $pointsEarned,
            'earned',
            $orderId,
            $description,
            $this->common
        );

        if (!$awardResult) {
            $this->response(array(
                'success' => false,
                'message' => 'Failed to award loyalty points'
            ), REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
            return;
        }

        // Get updated customer data to check new tier
        $updatedCustomer = $this->common->readdatadocument('Users', $customerId);
        $newPoints = isset($updatedCustomer['points']) ? intval($updatedCustomer['points']) : $currentPoints;
        $newTier = get_customer_tier_from_points($newPoints, $this->common);

        // Mark order as having loyalty points processed
        $this->markLoyaltyPointsProcessed($orderId, $pointsEarned);

        // Check for birthday bonus (if applicable)
        $birthdayBonusAwarded = false;
        if (isset($settings['birthdayBonusEnabled']) && $settings['birthdayBonusEnabled']) {
            $birthdayResult = check_birthday_bonus($customerId, $this->common);
            if ($birthdayResult) {
                $birthdayBonusAwarded = true;
            }
        }

        // Build response
        $response = array(
            'success' => true,
            'message' => 'Loyalty points processed successfully',
            'data' => array(
                'orderId' => $orderId,
                'customerId' => $customerId,
                'orderTotal' => round($orderTotal, 2),
                'points' => array(
                    'earned' => $pointsEarned,
                    'basePoints' => round($basePoints, 2),
                    'multiplier' => round($multiplier, 2),
                    'pointsBefore' => $currentPoints,
                    'pointsAfter' => $newPoints,
                    'breakdown' => $breakdown
                ),
                'tier' => array(
                    'oldTier' => $oldTier,
                    'newTier' => $newTier,
                    'tierChanged' => $oldTier != $newTier
                ),
                'birthdayBonusAwarded' => $birthdayBonusAwarded
            )
        );

        $this->response($response, REST_Controller::HTTP_OK);
    }

    /**
     * Check if loyalty points were already processed for an order
     * @param string $orderId Order ID
     * @return bool True if already processed, false otherwise
     */
    private function isLoyaltyPointsProcessed($orderId)
    {
        // Check if there's a loyalty transaction for this order
        $transactions = $this->common->readdatafromcollectionwhereclause('LoyaltyTransactions');
        
        if (!empty($transactions)) {
            foreach ($transactions as $transaction) {
                if (isset($transaction['orderId']) && $transaction['orderId'] == $orderId && 
                    isset($transaction['type']) && $transaction['type'] == 'earned') {
                    return true;
                }
            }
        }

        // Also check if order has a flag indicating points were processed
        $order = $this->common->readdatadocument('Orders', $orderId);
        if (!empty($order) && isset($order['loyaltyPointsProcessed']) && $order['loyaltyPointsProcessed'] === true) {
            return true;
        }

        return false;
    }

    /**
     * Mark order as having loyalty points processed
     * @param string $orderId Order ID
     * @param int $pointsEarned Points earned
     */
    private function markLoyaltyPointsProcessed($orderId, $pointsEarned)
    {
        $updateData = array(
            'loyaltyPointsProcessed' => true,
            'loyaltyPointsEarned' => $pointsEarned,
            'loyaltyPointsProcessedAt' => time() * 1000
        );
        $this->common->updatedatamodel('Orders', $orderId, $updateData);
    }

    /**
     * Apply Loyalty Points API - Calculate discount when user applies loyalty points
     * POST /api/applyLoyaltyPoints
     * 
     * Required parameters:
     * - userId: Customer User ID
     * - totalAmount: Order total amount before discount
     * 
     * Optional parameters:
     * - pointsToRedeem: Specific number of points to redeem (if not provided, uses all available points)
     * 
     * This endpoint:
     * 1. Fetches user's current loyalty points
     * 2. Calculates discount based on points (100 points = $1 by default, configurable)
     * 3. Applies discount to total amount
     * 4. Returns discounted price and updated tier/level after points are applied
     */
    public function applyLoyaltyPoints_post()
    {
        $userId = $this->post('userId');
        $totalAmount = $this->post('totalAmount');
        $pointsToRedeem = $this->post('pointsToRedeem'); // Optional: specific points to redeem

        // Validate required fields
        if (!$userId) {
            $this->response(array(
                'success' => false,
                'message' => 'User ID is required'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        if (!$totalAmount || floatval($totalAmount) <= 0) {
            $this->response(array(
                'success' => false,
                'message' => 'Valid total amount is required'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        $totalAmount = floatval($totalAmount);

        // Get customer data
        $customer = $this->common->readdatadocument('Users', $userId);
        if (empty($customer)) {
            $this->response(array(
                'success' => false,
                'message' => 'Customer not found'
            ), REST_Controller::HTTP_NOT_FOUND);
            return;
        }

        // Verify user is a customer
        $userRole = isset($customer['userRole']) ? $customer['userRole'] : '';
        if ($userRole != 'user') {
            $this->response(array(
                'success' => false,
                'message' => 'User is not a customer. Only customers can redeem loyalty points.'
            ), REST_Controller::HTTP_BAD_REQUEST);
            return;
        }

        // Get current points
        $currentPoints = isset($customer['points']) ? intval($customer['points']) : 0;
        $currentTier = get_customer_tier_from_points($currentPoints, $this->common);

        if ($currentPoints <= 0) {
            $this->response(array(
                'success' => false,
                'message' => 'Customer has no loyalty points to redeem',
                'data' => array(
                    'currentPoints' => 0,
                    'currentTier' => $currentTier,
                    'totalAmount' => $totalAmount,
                    'discountedAmount' => $totalAmount,
                    'discount' => 0,
                    'pointsRedeemed' => 0
                )
            ), REST_Controller::HTTP_OK);
            return;
        }

        // Get loyalty settings for points conversion rate
        $settings = get_loyalty_settings($this->common);
        
        // Default: 100 points = $1 discount
        // Check for pointsForReward setting, or use default conversion
        // Standard conversion: 100 points = $1 discount
        $pointsPerDollar = 100; // Default: 100 points per dollar discount
        
        // Check if there's a custom conversion rate in settings
        if (isset($settings['pointsForReward']) && $settings['pointsForReward'] > 0) {
            $pointsPerDollar = floatval($settings['pointsForReward']);
        } elseif (isset($settings['pointsPerDollar']) && $settings['pointsPerDollar'] > 0) {
            // Alternative: use pointsPerDollar as inverse (if 1 point per dollar earned, then 100 points = $1 discount)
            // This is a reasonable default conversion
            $pointsPerDollar = 100;
        }

        // Determine how many points to redeem
        $maxDiscountPoints = $currentPoints; // Can't redeem more than available
        $maxDiscountAmount = ($maxDiscountPoints / $pointsPerDollar); // Maximum discount in dollars
        
        // If specific points requested, use that (but not more than available)
        if ($pointsToRedeem !== null && $pointsToRedeem !== '') {
            $pointsToRedeem = intval($pointsToRedeem);
            if ($pointsToRedeem > $currentPoints) {
                $pointsToRedeem = $currentPoints; // Can't redeem more than available
            }
            if ($pointsToRedeem < 0) {
                $pointsToRedeem = 0;
            }
        } else {
            // Use all available points (up to order total)
            $pointsToRedeem = $maxDiscountPoints;
        }

        // Calculate discount
        $discountAmount = ($pointsToRedeem / $pointsPerDollar);
        
        // Don't allow discount to exceed order total
        if ($discountAmount > $totalAmount) {
            $discountAmount = $totalAmount;
            $pointsToRedeem = intval($discountAmount * $pointsPerDollar); // Recalculate points needed
        }

        // Calculate final amount after discount
        $discountedAmount = max(0, $totalAmount - $discountAmount);

        // Calculate points after redemption (for tier calculation)
        $pointsAfterRedemption = $currentPoints - $pointsToRedeem;
        $tierAfterRedemption = get_customer_tier_from_points($pointsAfterRedemption, $this->common);

        // Build response
        $response = array(
            'success' => true,
            'message' => 'Loyalty points applied successfully',
            'data' => array(
                'userId' => $userId,
                'pricing' => array(
                    'originalAmount' => round($totalAmount, 2),
                    'discountAmount' => round($discountAmount, 2),
                    'finalAmount' => round($discountedAmount, 2),
                    'pointsRedeemed' => $pointsToRedeem,
                    'pointsPerDollar' => $pointsPerDollar,
                    'discountPercentage' => $totalAmount > 0 ? round(($discountAmount / $totalAmount) * 100, 2) : 0
                ),
                'loyalty' => array(
                    'pointsBefore' => $currentPoints,
                    'pointsAfter' => $pointsAfterRedemption,
                    'pointsRedeemed' => $pointsToRedeem,
                    'tierBefore' => $currentTier,
                    'tierAfter' => $tierAfterRedemption,
                    'tierChanged' => $currentTier != $tierAfterRedemption,
                    'maxDiscountAvailable' => round($maxDiscountAmount, 2),
                    'maxPointsAvailable' => $currentPoints
                )
            )
        );

        $this->response($response, REST_Controller::HTTP_OK);
    }
}
