<?php
namespace PaymentGateway\Paypal;

use PaymentGateway\BaseGateway;
use Exception;

class Gateway extends BaseGateway
{
    private $apiUrl;
    private $clientId;
    private $clientSecret;
    private $accessToken;
    
    public function __construct($config, $conn)
    {
        parent::__construct($config, $conn);
        
        $this->clientId = $config['client_id'] ?? '';
        $this->clientSecret = $config['client_secret'] ?? '';
        
        // Set API URL based on mode
        $mode = $config['mode'] ?? 'sandbox';
        $this->apiUrl = $mode === 'live' 
            ? 'https://api.paypal.com' 
            : 'https://api.sandbox.paypal.com';
    }
    
    public function processPayment($data)
    {
        try {
            $accessToken = $this->getAccessToken();
            if (!$accessToken) {
                throw new Exception('Failed to get PayPal access token');
            }
            
            // Create PayPal order
            $orderData = [
                'intent' => 'CAPTURE',
                'purchase_units' => [
                    [
                        'reference_id' => 'payment_' . $data['payment_id'],
                        'amount' => [
                            'currency_code' => $this->config['currency'] ?? 'USD',
                            'value' => number_format($data['amount'], 2, '.', '')
                        ],
                        'description' => 'Subscription renewal for user ' . $data['user_id']
                    ]
                ],
                'application_context' => [
                    'return_url' => $data['return_url'],
                    'cancel_url' => $data['cancel_url'],
                    'brand_name' => 'NuxSaaS',
                    'landing_page' => 'BILLING'
                ]
            ];
            
            $response = $this->makeApiCall('/v2/checkout/orders', 'POST', $orderData);
            
            if ($response && isset($response['id'])) {
                // Update payment with PayPal order ID
                $this->updatePaymentStatus($data['payment_id'], 'processing', [
                    'paypal_order_id' => $response['id'],
                    'paypal_response' => $response
                ]);
                
                // Get approval URL
                $approvalUrl = '';
                foreach ($response['links'] as $link) {
                    if ($link['rel'] === 'approve') {
                        $approvalUrl = $link['href'];
                        break;
                    }
                }
                
                return [
                    'success' => true,
                    'redirect_url' => $approvalUrl,
                    'payment_id' => $response['id']
                ];
            } else {
                throw new Exception('Invalid PayPal response');
            }
            
        } catch (Exception $e) {
            error_log('PayPal payment error: ' . $e->getMessage());
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
    
    public function handleWebhook()
    {
        try {
            $input = file_get_contents('php://input');
            $event = json_decode($input, true);
            
            if (!$event) {
                throw new Exception('Invalid webhook payload');
            }
            
            // Verify webhook signature (simplified - implement proper verification)
            $headers = getallheaders();
            if (!$this->verifyWebhookSignature($input, $headers)) {
                throw new Exception('Webhook signature verification failed');
            }
            
            $eventType = $event['event_type'] ?? '';
            
            switch ($eventType) {
                case 'PAYMENT.CAPTURE.COMPLETED':
                    $this->handlePaymentCompleted($event);
                    break;
                    
                case 'PAYMENT.CAPTURE.DENIED':
                    $this->handlePaymentDenied($event);
                    break;
                    
                case 'PAYMENT.CAPTURE.PENDING':
                    $this->handlePaymentPending($event);
                    break;
                    
                default:
                    error_log('Unhandled PayPal webhook event: ' . $eventType);
            }
            
            return ['success' => true];
            
        } catch (Exception $e) {
            error_log('PayPal webhook error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    public function verifyPayment($paymentId)
    {
        try {
            $payment = $this->getPayment($paymentId);
            if (!$payment) {
                return ['success' => false, 'message' => 'Payment not found'];
            }
            
            $gatewayResponse = json_decode($payment['gateway_response'], true);
            $paypalOrderId = $gatewayResponse['paypal_order_id'] ?? '';
            
            if (!$paypalOrderId) {
                return ['success' => false, 'message' => 'PayPal order ID not found'];
            }
            
            $accessToken = $this->getAccessToken();
            $response = $this->makeApiCall("/v2/checkout/orders/{$paypalOrderId}", 'GET');
            
            if ($response && isset($response['status'])) {
                return [
                    'success' => true,
                    'status' => $response['status'],
                    'details' => $response
                ];
            }
            
            return ['success' => false, 'message' => 'Failed to verify payment'];
            
        } catch (Exception $e) {
            error_log('PayPal payment verification error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
    
    public function getConfigFields()
    {
        return [
            'mode' => [
                'label' => 'Mode',
                'type' => 'select',
                'options' => [
                    'sandbox' => 'Sandbox (Testing)',
                    'live' => 'Live (Production)'
                ],
                'required' => true
            ],
            'client_id' => [
                'label' => 'Client ID',
                'type' => 'text',
                'required' => true
            ],
            'client_secret' => [
                'label' => 'Client Secret',
                'type' => 'password',
                'required' => true
            ],
            'currency' => [
                'label' => 'Currency',
                'type' => 'select',
                'options' => [
                    'USD' => 'US Dollar',
                    'EUR' => 'Euro',
                    'GBP' => 'British Pound'
                ],
                'required' => true
            ]
        ];
    }
    
    public function testConnection()
    {
        try {
            $accessToken = $this->getAccessToken();
            
            if ($accessToken) {
                return [
                    'success' => true,
                    'message' => 'PayPal connection successful'
                ];
            } else {
                return [
                    'success' => false,
                    'message' => 'Failed to get access token'
                ];
            }
            
        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
    
    private function getAccessToken()
    {
        if ($this->accessToken) {
            return $this->accessToken;
        }
        
        try {
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $this->apiUrl . '/v1/oauth2/token',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
                CURLOPT_USERPWD => $this->clientId . ':' . $this->clientSecret,
                CURLOPT_HTTPHEADER => [
                    'Accept: application/json',
                    'Accept-Language: en_US'
                ],
                CURLOPT_SSL_VERIFYPEER => false
            ]);
            
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            if ($httpCode === 200) {
                $data = json_decode($response, true);
                $this->accessToken = $data['access_token'] ?? '';
                return $this->accessToken;
            }
            
        } catch (Exception $e) {
            error_log('PayPal access token error: ' . $e->getMessage());
        }
        
        return false;
    }
    
    private function makeApiCall($endpoint, $method = 'GET', $data = null)
    {
        try {
            $ch = curl_init();
            
            $headers = [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->accessToken
            ];
            
            curl_setopt_array($ch, [
                CURLOPT_URL => $this->apiUrl . $endpoint,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_SSL_VERIFYPEER => false
            ]);
            
            if ($method === 'POST') {
                curl_setopt($ch, CURLOPT_POST, true);
                if ($data) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
                }
            }
            
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            if ($httpCode >= 200 && $httpCode < 300) {
                return json_decode($response, true);
            } else {
                error_log("PayPal API error: HTTP {$httpCode} - {$response}");
                return false;
            }
            
        } catch (Exception $e) {
            error_log('PayPal API call error: ' . $e->getMessage());
            return false;
        }
    }
    
    private function verifyWebhookSignature($payload, $headers)
    {
        // Simplified signature verification
        // In production, implement proper PayPal webhook signature verification
        return true;
    }
    
    private function handlePaymentCompleted($event)
    {
        $orderId = $event['resource']['supplementary_data']['related_ids']['order_id'] ?? '';
        
        if ($orderId) {
            // Find payment by PayPal order ID
            $sql = "SELECT id, subscription_id FROM payments WHERE JSON_EXTRACT(gateway_response, '$.paypal_order_id') = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$orderId]);
            $payment = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if ($payment) {
                $this->updatePaymentStatus($payment['id'], 'completed', $event);
                
                if ($payment['subscription_id']) {
                    $this->processSubscriptionRenewal($payment['subscription_id'], $payment['id']);
                }
                
                $this->sendPaymentNotification($payment['id'], 'completed');
            }
        }
    }
    
    private function handlePaymentDenied($event)
    {
        $orderId = $event['resource']['supplementary_data']['related_ids']['order_id'] ?? '';
        
        if ($orderId) {
            $sql = "SELECT id FROM payments WHERE JSON_EXTRACT(gateway_response, '$.paypal_order_id') = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$orderId]);
            $payment = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if ($payment) {
                $this->updatePaymentStatus($payment['id'], 'failed', $event);
                $this->sendPaymentNotification($payment['id'], 'failed');
            }
        }
    }
    
    private function handlePaymentPending($event)
    {
        $orderId = $event['resource']['supplementary_data']['related_ids']['order_id'] ?? '';
        
        if ($orderId) {
            $sql = "SELECT id FROM payments WHERE JSON_EXTRACT(gateway_response, '$.paypal_order_id') = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$orderId]);
            $payment = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if ($payment) {
                $this->updatePaymentStatus($payment['id'], 'processing', $event);
            }
        }
    }
}
