<?php
/**
 * Order Controller
 * Handles order creation, tracking, and management with 80% profit markup
 */

namespace App\Controller;

use App\Classes\Api\MrGoViralAPI;
use App\Classes\Currency\CurrencyManager;

class OrderController {
    protected $db;
    protected $api;
    protected $currency;
    
    const PROFIT_MARKUP = 0.80; // 80% markup on provider price
    
    public function __construct($db) {
        $this->db = $db;
        $this->api = new MrGoViralAPI();
        $this->currency = CurrencyManager::getInstance();
    }
    
    /**
     * Get available services with markup pricing
     */
    public function getServices($search = null) {
        try {
            // Fetch from MrGoViral
            $servicesData = $this->api->getServices();
            
            if (!MrGoViralAPI::isSuccess($servicesData)) {
                return ['success' => false, 'error' => 'Failed to fetch services'];
            }
            
            $services = [];
            $servicesList = $servicesData['services'] ?? [];
            
            foreach ($servicesList as $service) {
                // Apply 80% markup
                $basePrice = $service['rate'] ?? $service['price'] ?? 0;
                $markupPrice = $basePrice * (1 + self::PROFIT_MARKUP);
                
                $serviceData = [
                    'id' => $service['service'] ?? $service['id'],
                    'name' => $service['name'] ?? '',
                    'description' => $service['description'] ?? '',
                    'category' => $service['category'] ?? 'General',
                    'base_price' => $basePrice,
                    'display_price' => $markupPrice,
                    'min_quantity' => $service['min'] ?? 1,
                    'max_quantity' => $service['max'] ?? 10000,
                    'refillable' => isset($service['refill']) && $service['refill'] == 1,
                    'refill_days' => $service['refill_days'] ?? null,
                ];
                
                // Apply search filter if provided
                if ($search) {
                    if (stripos($serviceData['name'], $search) === false && 
                        stripos($serviceData['category'], $search) === false) {
                        continue;
                    }
                }
                
                $services[] = $serviceData;
            }
            
            return [
                'success' => true,
                'services' => $services,
                'count' => count($services)
            ];
            
        } catch (\Exception $e) {
            error_log('Services Error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Get single service with markup
     */
    public function getService($serviceId) {
        try {
            $service = $this->api->getService($serviceId);
            
            if (!MrGoViralAPI::isSuccess($service)) {
                return ['success' => false, 'error' => 'Service not found'];
            }
            
            // Apply markup
            $basePrice = $service['rate'] ?? $service['price'] ?? 0;
            $markupPrice = $basePrice * (1 + self::PROFIT_MARKUP);
            
            return [
                'success' => true,
                'service' => [
                    'id' => $service['service'] ?? $service['id'],
                    'name' => $service['name'] ?? '',
                    'base_price' => $basePrice,
                    'display_price' => $markupPrice,
                    'min_quantity' => $service['min'] ?? 1,
                    'max_quantity' => $service['max'] ?? 10000,
                ]
            ];
            
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Create a new order
     */
    public function createOrder($userId, $serviceId, $link, $quantity) {
        try {
            $this->db->beginTransaction();
            
            // Validate quantity
            if ($quantity < 1) {
                throw new \Exception('Quantity must be at least 1');
            }
            
            // Get service details
            $stmt = $this->db->prepare('SELECT * FROM services WHERE service_id = ?');
            $stmt->execute([$serviceId]);
            $service = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if (!$service) {
                throw new \Exception('Service not found');
            }
            
            // Validate quantity against limits
            if ($quantity < $service['min_quantity'] || $quantity > $service['max_quantity']) {
                throw new \Exception('Quantity out of range');
            }
            
            // Calculate price (base price with markup)
            $displayPrice = $service['base_price'] * $quantity * (1 + self::PROFIT_MARKUP);
            $costPrice = $service['base_price'] * $quantity;
            $platformProfit = $displayPrice - $costPrice;
            
            // Get user and check balance
            $userStmt = $this->db->prepare('SELECT balance, primary_currency FROM users WHERE id = ?');
            $userStmt->execute([$userId]);
            $user = $userStmt->fetch(\PDO::FETCH_ASSOC);
            
            if (!$user) {
                throw new \Exception('User not found');
            }
            
            // Check if user has sufficient balance
            if ($user['balance'] < $displayPrice) {
                throw new \Exception('Insufficient balance. Required: ' . $displayPrice . ', Available: ' . $user['balance']);
            }
            
            // Place order with MrGoViral
            $mrgovOrder = $this->api->placeOrder($serviceId, $link, $quantity);
            
            if (!MrGoViralAPI::isSuccess($mrgovOrder)) {
                throw new \Exception('Failed to place order with provider: ' . MrGoViralAPI::getError($mrgovOrder));
            }
            
            $externalOrderId = $mrgovOrder['order'] ?? $mrgovOrder['order_id'] ?? null;
            
            if (!$externalOrderId) {
                throw new \Exception('No order ID returned from provider');
            }
            
            // Generate unique order ID
            $orderId = 'ORD-' . time() . '-' . $userId;
            
            // Create order record
            $orderStmt = $this->db->prepare('
                INSERT INTO orders 
                (order_id, user_id, service_id, external_order_id, link, quantity, status, price, currency, created_at)
                VALUES (?, ?, ?, ?, ?, ?, "processing", ?, ?, NOW())
            ');
            
            $orderStmt->execute([
                $orderId,
                $userId,
                $service['id'],
                $externalOrderId,
                $link,
                $quantity,
                $displayPrice,
                $user['primary_currency']
            ]);
            
            $orderDbId = $this->db->lastInsertId();
            
            // Deduct balance from user account
            $newBalance = $user['balance'] - $displayPrice;
            $balanceStmt = $this->db->prepare('UPDATE users SET balance = ? WHERE id = ?');
            $balanceStmt->execute([$newBalance, $userId]);
            
            // Log transaction
            $transStmt = $this->db->prepare('
                INSERT INTO transactions 
                (user_id, transaction_type, reference_id, description, amount, previous_balance, new_balance, status)
                VALUES (?, "order", ?, ?, ?, ?, ?, "completed")
            ');
            
            $transStmt->execute([
                $userId,
                $orderId,
                'Order: ' . $service['name'],
                $displayPrice,
                $user['balance'],
                $newBalance
            ]);
            
            $this->db->commit();
            
            // Queue email notification
            $this->queueOrderEmail($userId, $orderId, $service['name'], $quantity, $displayPrice);
            
            return [
                'success' => true,
                'message' => 'Order placed successfully',
                'order_id' => $orderId,
                'external_order_id' => $externalOrderId,
                'price' => $displayPrice,
                'currency' => $user['primary_currency'],
                'platform_profit' => $platformProfit,
                'new_balance' => $newBalance
            ];
            
        } catch (\Exception $e) {
            $this->db->rollBack();
            error_log('Order Error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Get user's orders
     */
    public function getUserOrders($userId, $limit = 50, $offset = 0) {
        try {
            $stmt = $this->db->prepare('
                SELECT o.*, s.name as service_name
                FROM orders o
                JOIN services s ON o.service_id = s.id
                WHERE o.user_id = ?
                ORDER BY o.created_at DESC
                LIMIT ? OFFSET ?
            ');
            $stmt->execute([$userId, $limit, $offset]);
            $orders = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            
            // Get total count
            $countStmt = $this->db->prepare('SELECT COUNT(*) as total FROM orders WHERE user_id = ?');
            $countStmt->execute([$userId]);
            $total = $countStmt->fetch(\PDO::FETCH_ASSOC)['total'];
            
            return [
                'success' => true,
                'orders' => $orders,
                'total' => $total,
                'limit' => $limit,
                'offset' => $offset
            ];
            
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Get order details
     */
    public function getOrder($orderId) {
        try {
            $stmt = $this->db->prepare('
                SELECT o.*, s.name as service_name, s.base_price
                FROM orders o
                JOIN services s ON o.service_id = s.id
                WHERE o.order_id = ? OR o.id = ?
            ');
            $stmt->execute([$orderId, $orderId]);
            $order = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if (!$order) {
                return ['success' => false, 'error' => 'Order not found'];
            }
            
            // Get status from provider if processing
            if ($order['status'] === 'processing') {
                $statusData = $this->api->getOrderStatus($order['external_order_id']);
                
                if (MrGoViralAPI::isSuccess($statusData)) {
                    $order['provider_status'] = $statusData['status'] ?? 'unknown';
                    $order['quantity_received'] = $statusData['quantity_received'] ?? 0;
                }
            }
            
            return ['success' => true, 'order' => $order];
            
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Queue order email notification
     */
    private function queueOrderEmail($userId, $orderId, $serviceName, $quantity, $price) {
        try {
            $user = $this->db->query("SELECT email FROM users WHERE id = $userId")->fetch(\PDO::FETCH_ASSOC);
            
            if ($user) {
                $subject = "Order Confirmation - $orderId";
                $template = 'order_confirmation';
                $data = [
                    'order_id' => $orderId,
                    'service_name' => $serviceName,
                    'quantity' => $quantity,
                    'price' => $price
                ];
                
                $stmt = $this->db->prepare('
                    INSERT INTO email_queue (recipient, subject, template, data, status)
                    VALUES (?, ?, ?, ?, "pending")
                ');
                $stmt->execute([$user['email'], $subject, $template, json_encode($data)]);
            }
        } catch (\Exception $e) {
            error_log('Email Queue Error: ' . $e->getMessage());
        }
    }
}
?>
