<?php
/**
 * Order Controller
 * Handle order operations and tracking
 */

namespace Controllers;

use Core\Auth;
use Core\Helpers;
use Models\Order;
use Models\User;

class OrderController extends Controller {
    
    /**
     * Get orders for current user
     */
    public function index($params = []) {
        $userId = $this->requireAuth();
        $user = Auth::user();
        
        $orderModel = new Order();
        $orders = [];
        
        switch ($user['role']) {
            case 'admin':
                $orders = $orderModel->getAll();
                break;
            case 'pharmacy':
                $pharmacy = (new \Models\Pharmacy())->findByUserId($userId);
                if ($pharmacy) {
                    $status = $_GET['status'] ?? null;
                    $orders = $orderModel->getByPharmacy($pharmacy['id'], $status);
                }
                break;
            case 'courier':
                $courier = (new \Models\Courier())->findByUserId($userId);
                if ($courier) {
                    $status = $_GET['status'] ?? null;
                    $orders = $orderModel->getByCourier($courier['id'], $status);
                }
                break;
            case 'client':
                $orders = $orderModel->getByClient($userId);
                break;
        }
        
        $this->success($orders);
    }
    
    /**
     * Get single order details
     */
    public function show($params = []) {
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        $orderModel = new Order();
        $order = $orderModel->getWithDetails($params['id']);
        
        if (!$order) {
            $this->error('Commande non trouvée', 404);
        }
        
        // Check if user can view this order
        if (Auth::check()) {
            $user = Auth::user();
            $canView = false;
            
            switch ($user['role']) {
                case 'admin':
                    $canView = true;
                    break;
                case 'client':
                    $canView = $order['client_id'] === $user['id'];
                    break;
                case 'pharmacy':
                    $pharmacy = (new \Models\Pharmacy())->findByUserId($user['id']);
                    $canView = $pharmacy && $order['pharmacy_id'] === $pharmacy['id'];
                    break;
                case 'courier':
                    $courier = (new \Models\Courier())->findByUserId($user['id']);
                    $canView = $courier && $order['courier_id'] === $courier['id'];
                    break;
            }
            
            if (!$canView) {
                $this->error('Permission refusée', 403);
            }
        }
        
        $this->success($order);
    }
    
    /**
     * Update order status
     */
    public function updateStatus($params = []) {
        $userId = $this->requireAuth();
        $input = $this->getInput();
        
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        $this->validateRequired($input, ['status']);
        
        try {
            $orderModel = new Order();
            $order = $orderModel->findById($params['id']);
            
            if (!$order) {
                $this->error('Commande non trouvée', 404);
            }
            
            // Check permissions
            $user = Auth::user();
            $canUpdate = false;
            
            switch ($user['role']) {
                case 'admin':
                    $canUpdate = true;
                    break;
                case 'pharmacy':
                    $pharmacy = (new \Models\Pharmacy())->findByUserId($userId);
                    $canUpdate = $pharmacy && $order['pharmacy_id'] === $pharmacy['id'];
                    break;
                case 'courier':
                    $courier = (new \Models\Courier())->findByUserId($userId);
                    $canUpdate = $courier && $order['courier_id'] === $courier['id'];
                    // Only allow certain status updates
                    $allowedStatuses = ['PICKED_UP', 'DELIVERED'];
                    $canUpdate = $canUpdate && in_array($input['status'], $allowedStatuses);
                    break;
            }
            
            if (!$canUpdate) {
                $this->error('Permission refusée', 403);
            }
            
            $orderModel->updateStatus($params['id'], $input['status']);
            
            $this->log("Order status updated: {$params['id']} -> {$input['status']}");
            
            $this->success([], 'Statut mis à jour avec succès');
            
        } catch (\Exception $e) {
            $this->log("Order status update failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors de la mise à jour: ' . $e->getMessage());
        }
    }
    
    /**
     * Pharmacy confirms or rejects order
     */
    public function pharmacyResponse($params = []) {
        $userId = $this->requireRole('pharmacy');
        $input = $this->getInput();
        
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        $this->validateRequired($input, ['action']);
        
        if (!in_array($input['action'], ['accept', 'reject'])) {
            $this->error('Action invalide');
        }
        
        try {
            $orderModel = new Order();
            $pharmacy = (new \Models\Pharmacy())->findByUserId($userId);
            
            if (!$pharmacy) {
                $this->error('Profil pharmacie non trouvé');
            }
            
            $order = $orderModel->findById($params['id']);
            if (!$order) {
                $this->error('Commande non trouvée', 404);
            }
            
            if ($order['pharmacy_id'] !== $pharmacy['id']) {
                $this->error('Permission refusée', 403);
            }
            
            if ($input['action'] === 'accept') {
                if (!isset($input['unit_price']) || $input['unit_price'] <= 0) {
                    $this->error('Prix unitaire requis');
                }
                
                $orderModel->pharmacyConfirm($params['id'], (int)$input['unit_price']);
                
                // Try to find and assign courier
                $pharmacy_data = (new \Models\Pharmacy())->findById($pharmacy['id']);
                $couriers = $orderModel->findNearbyCouriers($pharmacy_data['lat'], $pharmacy_data['lng']);
                
                if (!empty($couriers)) {
                    $orderModel->assignCourier($params['id'], $couriers[0]['id']);
                    $message = 'Commande acceptée et livreur assigné';
                } else {
                    $message = 'Commande acceptée, recherche de livreur en cours';
                }
                
                $this->log("Pharmacy accepted order: {$params['id']}");
                
            } else {
                $reason = $input['reason'] ?? 'Stock indisponible';
                $orderModel->pharmacyReject($params['id'], $reason);
                
                $this->log("Pharmacy rejected order: {$params['id']}");
                $message = 'Commande refusée';
            }
            
            $this->success([], $message);
            
        } catch (\Exception $e) {
            $this->log("Pharmacy response failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors du traitement: ' . $e->getMessage());
        }
    }
    
    /**
     * Courier accepts order
     */
    public function courierAccept($params = []) {
        $userId = $this->requireRole('courier');
        
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        try {
            $orderModel = new Order();
            $courier = (new \Models\Courier())->findByUserId($userId);
            
            if (!$courier) {
                $this->error('Profil livreur non trouvé');
            }
            
            $order = $orderModel->findById($params['id']);
            if (!$order) {
                $this->error('Commande non trouvée', 404);
            }
            
            if ($order['status'] !== 'PHARMACY_CONFIRMED') {
                $this->error('Commande non disponible pour livraison');
            }
            
            if (!$courier['available']) {
                $this->error('Livreur non disponible');
            }
            
            $orderModel->assignCourier($params['id'], $courier['id']);
            
            $this->log("Courier accepted order: {$params['id']}");
            
            $this->success([], 'Livraison acceptée');
            
        } catch (\Exception $e) {
            $this->log("Courier accept failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors de l\'acceptation: ' . $e->getMessage());
        }
    }
    
    /**
     * Get order tracking information
     */
    public function tracking($params = []) {
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        $orderModel = new Order();
        $order = $orderModel->getWithDetails($params['id']);
        
        if (!$order) {
            $this->error('Commande non trouvée', 404);
        }
        
        // Calculate estimated arrival time
        $eta = null;
        if (in_array($order['status'], ['COURIER_ASSIGNED', 'PICKED_UP'])) {
            $baseTime = $order['status'] === 'PICKED_UP' ? 8 : 15;
            $eta = $baseTime + ($order['distance_km'] ? round($order['distance_km'] * 2) : 5);
        }
        
        // Add courier position (simulated for demo)
        $courierPosition = null;
        if ($order['courier_id'] && $order['pharmacy_lat']) {
            $courierPosition = [
                'lat' => ($order['pharmacy_lat'] + $order['client_lat']) / 2,
                'lng' => ($order['pharmacy_lng'] + $order['client_lng']) / 2
            ];
        }
        
        $trackingData = [
            'order' => $order,
            'eta_minutes' => $eta,
            'courier_position' => $courierPosition,
            'last_updated' => date('Y-m-d H:i:s')
        ];
        
        $this->success($trackingData);
    }
    
    /**
     * Get receipt for delivered order
     */
    public function receipt($params = []) {
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        $orderModel = new Order();
        $order = $orderModel->getWithDetails($params['id']);
        
        if (!$order) {
            $this->error('Commande non trouvée', 404);
        }
        
        if (!in_array($order['status'], ['DELIVERED', 'CLOSED'])) {
            $this->error('Reçu non disponible pour cette commande');
        }
        
        // Check permissions if user is logged in
        if (Auth::check()) {
            $user = Auth::user();
            $canView = false;
            
            switch ($user['role']) {
                case 'admin':
                    $canView = true;
                    break;
                case 'client':
                    $canView = $order['client_id'] === $user['id'];
                    break;
                case 'pharmacy':
                    $pharmacy = (new \Models\Pharmacy())->findByUserId($user['id']);
                    $canView = $pharmacy && $order['pharmacy_id'] === $pharmacy['id'];
                    break;
                case 'courier':
                    $courier = (new \Models\Courier())->findByUserId($user['id']);
                    $canView = $courier && $order['courier_id'] === $courier['id'];
                    break;
            }
            
            if (!$canView) {
                $this->error('Permission refusée', 403);
            }
        }
        
        // Generate receipt data
        $receipt = [
            'order_id' => $order['id'],
            'date' => $order['created_at'],
            'client_info' => [
                'name' => $order['client_name'] ?? 'Client',
                'phone' => $order['client_phone'],
                'address' => $order['client_address']
            ],
            'pharmacy_info' => [
                'name' => $order['pharmacy_name'],
                'address' => $order['pharmacy_address']
            ],
            'courier_info' => [
                'name' => $order['courier_name'],
                'vehicle' => $order['vehicle_type']
            ],
            'items' => [
                'medicine_name' => $order['medicine_name'],
                'quantity' => $order['qty'],
                'unit_price' => $order['med_price_total'] / $order['qty'],
                'total_price' => $order['med_price_total']
            ],
            'fees' => [
                'medicine_total' => $order['med_price_total'],
                'service_fee' => $order['service_fee'],
                'delivery_fee' => $order['delivery_fee'],
                'total' => $order['med_price_total'] + $order['service_fee'] + $order['delivery_fee']
            ],
            'distance' => $order['distance_km'],
            'payment_distribution' => Helpers::calculatePaymentDistribution(
                $order['med_price_total'],
                $order['delivery_fee']
            )
        ];
        
        $this->success($receipt);
    }
    
    /**
     * Cancel order (client only, before pharmacy confirmation)
     */
    public function cancel($params = []) {
        $userId = $this->requireRole('client');
        
        if (!isset($params['id'])) {
            $this->error('ID de commande requis');
        }
        
        try {
            $orderModel = new Order();
            $order = $orderModel->findById($params['id']);
            
            if (!$order) {
                $this->error('Commande non trouvée', 404);
            }
            
            if ($order['client_id'] !== $userId) {
                $this->error('Permission refusée', 403);
            }
            
            if ($order['status'] !== 'CREATED') {
                $this->error('Commande ne peut plus être annulée');
            }
            
            $orderModel->updateStatus($params['id'], 'CLOSED');
            $orderModel->addEvent($params['id'], 'ORDER_CANCELLED', [
                'cancelled_by' => 'client'
            ]);
            
            $this->log("Order cancelled: {$params['id']}");
            
            $this->success([], 'Commande annulée avec succès');
            
        } catch (\Exception $e) {
            $this->log("Order cancellation failed: " . $e->getMessage(), 'error');
            $this->error('Erreur lors de l\'annulation: ' . $e->getMessage());
        }
    }
}
?>
