<?php
namespace App\Controllers;

use PDO;
use Exception;

class PaymentGateways
{
    private $conn;
    private $gatewayPath;
    
    public function __construct()
    {
        global $conn;
        $this->conn = $conn;
        $this->gatewayPath = realpath(__DIR__ . '/../../addons/payment_gateways/');
    }
    
    public function index()
    {
        $gateways = $this->getAllGateways();
        include realpath(__DIR__ . '/../views/payment_gateways.php');
    }
    
    public function install()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $gatewayId = $_POST['gateway_id'] ?? '';
            $config = $_POST['config'] ?? [];
            
            if ($this->installGateway($gatewayId, $config)) {
                $_SESSION['success'] = "Payment gateway installed successfully!";
            } else {
                $_SESSION['error'] = "Failed to install payment gateway.";
            }
        }
        
        header('Location: /payment-gateways');
        exit;
    }
    
    public function configure()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $gatewayId = $_POST['gateway_id'] ?? '';
            $config = $_POST['config'] ?? [];
            
            if ($this->updateGatewayConfig($gatewayId, $config)) {
                $_SESSION['success'] = "Gateway configuration updated successfully!";
            } else {
                $_SESSION['error'] = "Failed to update gateway configuration.";
            }
        }
        
        header('Location: /payment-gateways');
        exit;
    }
    
    public function toggle()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $gatewayId = $_POST['gateway_id'] ?? '';
            $status = $_POST['status'] ?? 'inactive';
            
            if ($this->toggleGateway($gatewayId, $status)) {
                $_SESSION['success'] = "Gateway status updated successfully!";
            } else {
                $_SESSION['error'] = "Failed to update gateway status.";
            }
        }
        
        header('Location: /payment-gateways');
        exit;
    }
    
    public function processPayment()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $gatewayId = $_POST['gateway_id'] ?? '';
            $amount = floatval($_POST['amount'] ?? 0);
            $userId = $_POST['user_id'] ?? '';
            $subscriptionId = $_POST['subscription_id'] ?? '';
            
            $result = $this->initiatePayment($gatewayId, $amount, $userId, $subscriptionId);
            
            if ($result['success']) {
                // Redirect to payment page or return payment URL
                if (isset($result['redirect_url'])) {
                    header('Location: ' . $result['redirect_url']);
                    exit;
                } else {
                    echo json_encode($result);
                }
            } else {
                $_SESSION['error'] = $result['message'] ?? 'Payment initiation failed';
                header('Location: /dashboard');
                exit;
            }
        }
    }
    
    public function webhook()
    {
        $gatewayId = $_GET['gateway'] ?? '';
        $gateway = $this->loadGateway($gatewayId);
        
        if ($gateway) {
            $result = $gateway->handleWebhook();
            echo json_encode($result);
        } else {
            http_response_code(404);
            echo json_encode(['error' => 'Gateway not found']);
        }
    }
    
    private function getAllGateways()
    {
        // Get installed gateways from database
        $sql = "SELECT * FROM payment_gateways ORDER BY name";
        $stmt = $this->conn->query($sql);
        $installed = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        // Get available gateways from filesystem
        $available = $this->scanAvailableGateways();
        
        return [
            'installed' => $installed,
            'available' => $available
        ];
    }
    
    private function scanAvailableGateways()
    {
        $gateways = [];
        
        if (!is_dir($this->gatewayPath)) {
            mkdir($this->gatewayPath, 0755, true);
            return $gateways;
        }
        
        $dirs = scandir($this->gatewayPath);
        foreach ($dirs as $dir) {
            if ($dir === '.' || $dir === '..') continue;
            
            $gatewayDir = $this->gatewayPath . '/' . $dir;
            $manifestFile = $gatewayDir . '/manifest.json';
            
            if (is_dir($gatewayDir) && file_exists($manifestFile)) {
                $manifest = json_decode(file_get_contents($manifestFile), true);
                if ($manifest) {
                    $manifest['id'] = $dir;
                    $manifest['path'] = $gatewayDir;
                    $gateways[] = $manifest;
                }
            }
        }
        
        return $gateways;
    }
    
    private function installGateway($gatewayId, $config)
    {
        try {
            $gatewayDir = $this->gatewayPath . '/' . $gatewayId;
            $manifestFile = $gatewayDir . '/manifest.json';
            
            if (!file_exists($manifestFile)) {
                throw new Exception('Gateway manifest not found');
            }
            
            $manifest = json_decode(file_get_contents($manifestFile), true);
            
            // Check if gateway already installed
            $sql = "SELECT id FROM payment_gateways WHERE gateway_id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$gatewayId]);
            
            if ($stmt->fetch()) {
                throw new Exception('Gateway already installed');
            }
            
            // Install gateway
            $sql = "INSERT INTO payment_gateways (gateway_id, name, description, version, status, config, created_at) 
                    VALUES (?, ?, ?, ?, 'inactive', ?, NOW())";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([
                $gatewayId,
                $manifest['name'],
                $manifest['description'],
                $manifest['version'],
                json_encode($config)
            ]);
            
            // Run installation script if exists
            $installFile = $gatewayDir . '/install.php';
            if (file_exists($installFile)) {
                include $installFile;
            }
            
            return true;
        } catch (Exception $e) {
            error_log("Gateway installation error: " . $e->getMessage());
            return false;
        }
    }
    
    private function updateGatewayConfig($gatewayId, $config)
    {
        try {
            $sql = "UPDATE payment_gateways SET config = ?, updated_at = NOW() WHERE gateway_id = ?";
            $stmt = $this->conn->prepare($sql);
            return $stmt->execute([json_encode($config), $gatewayId]);
        } catch (Exception $e) {
            error_log("Gateway config update error: " . $e->getMessage());
            return false;
        }
    }
    
    private function toggleGateway($gatewayId, $status)
    {
        try {
            $sql = "UPDATE payment_gateways SET status = ?, updated_at = NOW() WHERE gateway_id = ?";
            $stmt = $this->conn->prepare($sql);
            return $stmt->execute([$status, $gatewayId]);
        } catch (Exception $e) {
            error_log("Gateway toggle error: " . $e->getMessage());
            return false;
        }
    }
    
    private function initiatePayment($gatewayId, $amount, $userId, $subscriptionId)
    {
        try {
            $gateway = $this->loadGateway($gatewayId);
            if (!$gateway) {
                throw new Exception('Gateway not found or inactive');
            }
            
            // Create payment record
            $sql = "INSERT INTO payments (user_id, subscription_id, gateway_id, amount, status, created_at) 
                    VALUES (?, ?, ?, ?, 'pending', NOW())";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$userId, $subscriptionId, $gatewayId, $amount]);
            $paymentId = $this->conn->lastInsertId();
            
            // Process payment through gateway
            $result = $gateway->processPayment([
                'payment_id' => $paymentId,
                'amount' => $amount,
                'user_id' => $userId,
                'subscription_id' => $subscriptionId,
                'return_url' => $_SERVER['HTTP_HOST'] . '/payment/return/' . $paymentId,
                'cancel_url' => $_SERVER['HTTP_HOST'] . '/payment/cancel/' . $paymentId,
                'webhook_url' => $_SERVER['HTTP_HOST'] . '/payment/webhook?gateway=' . $gatewayId
            ]);
            
            return $result;
            
        } catch (Exception $e) {
            error_log("Payment initiation error: " . $e->getMessage());
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
    
    private function loadGateway($gatewayId)
    {
        try {
            // Get gateway info from database
            $sql = "SELECT * FROM payment_gateways WHERE gateway_id = ? AND status = 'active'";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$gatewayId]);
            $gatewayInfo = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$gatewayInfo) {
                return null;
            }
            
            // Load gateway class
            $gatewayFile = $this->gatewayPath . '/' . $gatewayId . '/Gateway.php';
            if (!file_exists($gatewayFile)) {
                return null;
            }
            
            require_once $gatewayFile;
            
            $className = 'PaymentGateway\\' . ucfirst($gatewayId) . '\\Gateway';
            if (!class_exists($className)) {
                return null;
            }
            
            $config = json_decode($gatewayInfo['config'], true) ?: [];
            return new $className($config, $this->conn);
            
        } catch (Exception $e) {
            error_log("Gateway loading error: " . $e->getMessage());
            return null;
        }
    }
    
    public function getActiveGateways()
    {
        $sql = "SELECT * FROM payment_gateways WHERE status = 'active' ORDER BY name";
        $stmt = $this->conn->query($sql);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    public function getConfig()
    {
        $gatewayId = $_GET['gateway_id'] ?? '';
        
        try {
            $gateway = $this->loadGateway($gatewayId);
            if (!$gateway) {
                throw new Exception('Gateway not found');
            }
            
            $configFields = $gateway->getConfigFields();
            
            // Get current config
            $sql = "SELECT config FROM payment_gateways WHERE gateway_id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$gatewayId]);
            $currentConfig = $stmt->fetchColumn();
            $currentValues = json_decode($currentConfig, true) ?: [];
            
            // Generate HTML form
            $html = '<input type="hidden" name="gateway_id" value="' . htmlspecialchars($gatewayId) . '">';
            
            foreach ($configFields as $fieldName => $field) {
                $value = $currentValues[$fieldName] ?? ($field['default'] ?? '');
                $required = $field['required'] ? 'required' : '';
                
                $html .= '<div class="mb-3">';
                $html .= '<label class="form-label">' . htmlspecialchars($field['label']) . '</label>';
                
                switch ($field['type']) {
                    case 'text':
                        $html .= '<input type="text" class="form-control" name="config[' . $fieldName . ']" value="' . htmlspecialchars($value) . '" ' . $required . '>';
                        break;
                        
                    case 'password':
                        $html .= '<input type="password" class="form-control" name="config[' . $fieldName . ']" value="' . htmlspecialchars($value) . '" ' . $required . '>';
                        break;
                        
                    case 'select':
                        $html .= '<select class="form-control" name="config[' . $fieldName . ']" ' . $required . '>';
                        foreach ($field['options'] as $optValue => $optLabel) {
                            $selected = $value === $optValue ? 'selected' : '';
                            $html .= '<option value="' . htmlspecialchars($optValue) . '" ' . $selected . '>' . htmlspecialchars($optLabel) . '</option>';
                        }
                        $html .= '</select>';
                        break;
                        
                    case 'checkbox':
                        $checked = $value ? 'checked' : '';
                        $html .= '<div class="form-check">';
                        $html .= '<input type="checkbox" class="form-check-input" name="config[' . $fieldName . ']" value="1" ' . $checked . '>';
                        $html .= '<label class="form-check-label">' . htmlspecialchars($field['description'] ?? '') . '</label>';
                        $html .= '</div>';
                        break;
                }
                
                if (isset($field['description']) && $field['type'] !== 'checkbox') {
                    $html .= '<small class="form-text text-muted">' . htmlspecialchars($field['description']) . '</small>';
                }
                
                $html .= '</div>';
            }
            
            header('Content-Type: application/json');
            echo json_encode(['success' => true, 'html' => $html]);
            
        } catch (Exception $e) {
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
        }
    }
    
    public function getInstallForm()
    {
        $gatewayId = $_GET['gateway_id'] ?? '';
        
        try {
            // Load gateway manifest
            $manifestFile = $this->gatewayPath . '/' . $gatewayId . '/manifest.json';
            if (!file_exists($manifestFile)) {
                throw new Exception('Gateway manifest not found');
            }
            
            $manifest = json_decode(file_get_contents($manifestFile), true);
            if (!$manifest) {
                throw new Exception('Invalid gateway manifest');
            }
            
            // Generate installation form
            $html = '<input type="hidden" name="gateway_id" value="' . htmlspecialchars($gatewayId) . '">';
            $html .= '<div class="alert alert-info">';
            $html .= '<h6>' . htmlspecialchars($manifest['name']) . '</h6>';
            $html .= '<p>' . htmlspecialchars($manifest['description']) . '</p>';
            $html .= '<small><strong>Version:</strong> ' . htmlspecialchars($manifest['version']) . '</small><br>';
            $html .= '<small><strong>Author:</strong> ' . htmlspecialchars($manifest['author']) . '</small>';
            $html .= '</div>';
            
            // Add initial configuration fields if any
            if (isset($manifest['config_fields'])) {
                foreach ($manifest['config_fields'] as $field) {
                    if ($field['required']) {
                        $html .= '<div class="mb-3">';
                        $html .= '<label class="form-label">' . htmlspecialchars($field['label']) . '</label>';
                        
                        switch ($field['type']) {
                            case 'text':
                                $html .= '<input type="text" class="form-control" name="config[' . $field['name'] . ']" required>';
                                break;
                                
                            case 'password':
                                $html .= '<input type="password" class="form-control" name="config[' . $field['name'] . ']" required>';
                                break;
                                
                            case 'select':
                                $html .= '<select class="form-control" name="config[' . $field['name'] . ']" required>';
                                foreach ($field['options'] as $value => $label) {
                                    $selected = ($field['default'] ?? '') === $value ? 'selected' : '';
                                    $html .= '<option value="' . htmlspecialchars($value) . '" ' . $selected . '>' . htmlspecialchars($label) . '</option>';
                                }
                                $html .= '</select>';
                                break;
                        }
                        
                        if (isset($field['description'])) {
                            $html .= '<small class="form-text text-muted">' . htmlspecialchars($field['description']) . '</small>';
                        }
                        
                        $html .= '</div>';
                    }
                }
            }
            
            header('Content-Type: application/json');
            echo json_encode(['success' => true, 'html' => $html]);
            
        } catch (Exception $e) {
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
        }
    }
    
    public function testGateway()
    {
        $gatewayId = $_POST['gateway_id'] ?? '';
        
        try {
            $gateway = $this->loadGateway($gatewayId);
            if (!$gateway) {
                throw new Exception('Gateway not found or inactive');
            }
            
            $result = $gateway->testConnection();
            
            header('Content-Type: application/json');
            echo json_encode($result);
            
        } catch (Exception $e) {
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
        }
    }
    
    public function returnHandler()
    {
        $paymentId = $_GET['payment_id'] ?? '';
        
        try {
            if (!$paymentId) {
                throw new Exception('Payment ID not provided');
            }
            
            $payment = $this->getPayment($paymentId);
            if (!$payment) {
                throw new Exception('Payment not found');
            }
            
            $gateway = $this->loadGateway($payment['gateway_id']);
            if ($gateway) {
                $result = $gateway->verifyPayment($paymentId);
                
                if ($result['success'] && $result['status'] === 'completed') {
                    $_SESSION['success'] = 'Payment completed successfully!';
                } else {
                    $_SESSION['error'] = 'Payment verification failed: ' . ($result['message'] ?? 'Unknown error');
                }
            }
            
        } catch (Exception $e) {
            $_SESSION['error'] = 'Payment processing error: ' . $e->getMessage();
        }
        
        header('Location: /dashboard');
        exit;
    }
    
    public function cancelHandler()
    {
        $paymentId = $_GET['payment_id'] ?? '';
        
        try {
            if ($paymentId) {
                $this->updatePaymentStatus($paymentId, 'cancelled', ['reason' => 'User cancelled']);
            }
            
            $_SESSION['error'] = 'Payment was cancelled.';
            
        } catch (Exception $e) {
            $_SESSION['error'] = 'Error processing cancellation: ' . $e->getMessage();
        }
        
        header('Location: /dashboard');
        exit;
    }
    
    // Helper methods
    private function getPayment($paymentId)
    {
        try {
            $sql = "SELECT * FROM payments WHERE id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$paymentId]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Get payment error: " . $e->getMessage());
            return null;
        }
    }
    
    private function updatePaymentStatus($paymentId, $status, $details = [])
    {
        try {
            $sql = "UPDATE payments SET status = ?, gateway_response = ?, updated_at = NOW() WHERE id = ?";
            $stmt = $this->conn->prepare($sql);
            return $stmt->execute([$status, json_encode($details), $paymentId]);
        } catch (Exception $e) {
            error_log("Payment status update error: " . $e->getMessage());
            return false;
        }
    }
}
