<?php
namespace App\classes;

use mysqli;

/**
 * External API Order Service
 * Handles orders sent to external API and tracks profits
 */
class ExternalAPIOrderService
{
    private $conn;
    private $externalApiUrl;
    private $externalApiKey;

    public function __construct(mysqli $conn, $externalApiUrl = null, $externalApiKey = null)
    {
        $this->conn = $conn;
        $this->externalApiUrl = $externalApiUrl ?? $this->getConfig('external_api_url');
        $this->externalApiKey = $externalApiKey ?? $this->getConfig('external_api_key');
    }

    /**
     * Create order and send to external API
     */
    public function createOrder($packageSize, $networkType, $beneficiaryNumber, $agentId = null)
    {
        require_once __DIR__ . '/ExternalAPIPricingManager.php';
        $pricingManager = new \App\classes\ExternalAPIPricingManager($this->conn);

        // Get prices
        $adminPrice = $pricingManager->getAdminPrice($packageSize, $networkType);
        $externalPrice = $pricingManager->getExternalPrice($packageSize, $networkType);

        if ($adminPrice === null) {
            return ['success' => false, 'message' => 'Admin price not set for this package'];
        }

        if ($externalPrice === null) {
            return ['success' => false, 'message' => 'External API price not available for this package'];
        }

        $packageSizeGb = $this->normalizePackageSize($packageSize);
        $profit = $adminPrice - $externalPrice;

        // Create order record
        $stmt = $this->conn->prepare("
            INSERT INTO external_api_orders 
            (agent_id, network_type, package_size, package_size_gb, beneficiary_number, 
             admin_price, external_api_price, profit, status)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending')
        ");

        $packageSizeLabel = $this->formatPackageLabel($packageSizeGb);
        $stmt->bind_param("issdddd", $agentId, $networkType, $packageSizeLabel, $packageSizeGb, 
                         $beneficiaryNumber, $adminPrice, $externalPrice, $profit);
        
        if (!$stmt->execute()) {
            $stmt->close();
            return ['success' => false, 'message' => 'Failed to create order record'];
        }

        $orderId = $this->conn->insert_id;
        $stmt->close();

        // Send to external API
        $apiResponse = $this->sendToExternalAPI($packageSize, $networkType, $beneficiaryNumber);

        // Update order with API response
        $this->updateOrderWithAPIResponse($orderId, $apiResponse);

        return [
            'success' => $apiResponse['success'],
            'order_id' => $orderId,
            'message' => $apiResponse['message'] ?? 'Order created',
            'api_response' => $apiResponse
        ];
    }

    /**
     * Send order to external API
     */
    private function sendToExternalAPI($packageSize, $networkType, $beneficiaryNumber)
    {
        if (empty($this->externalApiUrl)) {
            return [
                'success' => false,
                'message' => 'External API URL not configured',
                'status' => 'error'
            ];
        }

        $data = [
            'package_size' => $packageSize,
            'network' => $networkType,
            'beneficiary' => $beneficiaryNumber
        ];

        $ch = curl_init($this->externalApiUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $this->externalApiKey
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            return [
                'success' => false,
                'message' => 'API Error: ' . $error,
                'status' => 'error',
                'http_code' => $httpCode
            ];
        }

        $responseData = json_decode($response, true);

        return [
            'success' => $httpCode >= 200 && $httpCode < 300,
            'message' => $responseData['message'] ?? 'Order sent to external API',
            'status' => $responseData['status'] ?? ($httpCode >= 200 && $httpCode < 300 ? 'success' : 'error'),
            'order_reference' => $responseData['order_reference'] ?? $responseData['reference'] ?? null,
            'http_code' => $httpCode,
            'response' => $responseData
        ];
    }

    /**
     * Update order with API response
     */
    private function updateOrderWithAPIResponse($orderId, $apiResponse)
    {
        $status = 'failed';
        if ($apiResponse['success']) {
            $status = $apiResponse['status'] === 'success' ? 'delivered' : 'processing';
        }

        $stmt = $this->conn->prepare("
            UPDATE external_api_orders 
            SET order_reference = ?,
                external_api_status = ?,
                external_api_response = ?,
                status = ?,
                error_message = ?
            WHERE id = ?
        ");

        $orderRef = $apiResponse['order_reference'] ?? null;
        $apiStatus = $apiResponse['status'] ?? null;
        $responseJson = json_encode($apiResponse['response'] ?? $apiResponse);
        $errorMsg = $apiResponse['success'] ? null : ($apiResponse['message'] ?? 'Unknown error');

        $stmt->bind_param("sssssi", $orderRef, $apiStatus, $responseJson, $status, $errorMsg, $orderId);
        $stmt->execute();
        $stmt->close();
    }

    /**
     * Get all external API orders
     */
    public function getAllOrders($filters = [])
    {
        $where = [];
        $params = [];
        $types = '';

        if (!empty($filters['status'])) {
            $where[] = "status = ?";
            $params[] = $filters['status'];
            $types .= 's';
        }

        if (!empty($filters['network_type'])) {
            $where[] = "network_type = ?";
            $params[] = $filters['network_type'];
            $types .= 's';
        }

        if (!empty($filters['date_from'])) {
            $where[] = "DATE(created_at) >= ?";
            $params[] = $filters['date_from'];
            $types .= 's';
        }

        if (!empty($filters['date_to'])) {
            $where[] = "DATE(created_at) <= ?";
            $params[] = $filters['date_to'];
            $types .= 's';
        }

        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        $sql = "
            SELECT eao.*, a.username, a.email
            FROM external_api_orders eao
            LEFT JOIN agents a ON eao.agent_id = a.id
            $whereClause
            ORDER BY eao.created_at DESC
        ";

        $stmt = $this->conn->prepare($sql);
        if (!$stmt) {
            error_log("ExternalAPIOrderService::getAllOrders - Prepare failed: " . $this->conn->error);
            return [];
        }
        
        if (!empty($params)) {
            $stmt->bind_param($types, ...$params);
        }
        
        if (!$stmt->execute()) {
            error_log("ExternalAPIOrderService::getAllOrders - Execute failed: " . $stmt->error);
            $stmt->close();
            return [];
        }
        
        $result = $stmt->get_result();
        
        $orders = [];
        while ($row = $result->fetch_assoc()) {
            $orders[] = $row;
        }
        
        $stmt->close();
        return $orders;
    }

    /**
     * Get profit statistics
     */
    public function getProfitStatistics($dateFrom = null, $dateTo = null)
    {
        $where = [];
        $params = [];
        $types = '';

        if ($dateFrom) {
            $where[] = "DATE(created_at) >= ?";
            $params[] = $dateFrom;
            $types .= 's';
        }

        if ($dateTo) {
            $where[] = "DATE(created_at) <= ?";
            $params[] = $dateTo;
            $types .= 's';
        }

        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        $sql = "
            SELECT 
                COUNT(*) as total_orders,
                SUM(admin_price) as total_revenue,
                SUM(external_api_price) as total_cost,
                SUM(profit) as total_profit,
                AVG(profit) as avg_profit,
                MIN(profit) as min_profit,
                MAX(profit) as max_profit
            FROM external_api_orders
            $whereClause
        ";

        $stmt = $this->conn->prepare($sql);
        if (!empty($params)) {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        $stats = $result->fetch_assoc();
        $stmt->close();

        return $stats;
    }

    /**
     * Get config value
     */
    private function getConfig($key)
    {
        $stmt = $this->conn->prepare("SELECT config_value FROM payment_config WHERE config_key = ?");
        $stmt->bind_param("s", $key);
        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result->fetch_assoc();
        $stmt->close();
        return $row ? $row['config_value'] : null;
    }

    /**
     * Format package label
     */
    private function formatPackageLabel($sizeGb)
    {
        if ($sizeGb < 1) {
            return round($sizeGb * 1024, 0) . 'MB';
        }
        return $sizeGb . 'GB';
    }

    /**
     * Normalize package size to GB
     */
    private function normalizePackageSize($packageSize)
    {
        $packageSize = trim((string)$packageSize);
        
        if (preg_match('/(\d+(?:\.\d+)?)\s*GB/i', $packageSize, $matches)) {
            return (float)$matches[1];
        }
        
        if (preg_match('/(\d+(?:\.\d+)?)\s*MB/i', $packageSize, $matches)) {
            return round(((float)$matches[1]) / 1024, 4);
        }
        
        // If just a number, assume GB
        $num = floatval(preg_replace('/[^0-9.]/', '', $packageSize));
        return $num > 0 ? $num : 0;
    }
}

