<?php
/**
 * Paystack Payment Gateway Integration
 * 
 * Handles all Paystack API interactions for payments and subscriptions
 */

class Paystack {
    private $config;
    private $apiKey;
    private $apiUrl;
    
    public function __construct() {
        $this->config = require APP_ROOT . '/config/paystack.php';
        $env = $this->config['environment'];
        $this->apiKey = trim($this->config[$env]['secret_key']);
        $this->apiUrl = $this->config['api_url'];

        // Validate key format
        if (empty($this->apiKey) || $this->apiKey === 'sk_test_xxxxxxxxxxxx' || $this->apiKey === 'sk_live_xxxxxxxxxxxx') {
            error_log('Paystack Error: Invalid or placeholder API key detected. Please configure your Paystack keys in config/paystack.php');
        }

        // Ensure key starts with correct prefix
        if (!str_starts_with($this->apiKey, 'sk_test_') && !str_starts_with($this->apiKey, 'sk_live_')) {
            error_log('Paystack Error: Secret key must start with "sk_test_" or "sk_live_". Current key: ' . substr($this->apiKey, 0, 10) . '...');
        }
    }
    
    /**
     * Initialize a transaction
     */
    public function initializeTransaction(array $data): array {
        $url = $this->apiUrl . '/transaction/initialize';
        
        $payload = [
            'email' => $data['email'],
            'amount' => $data['amount'] * 100, // Convert to kobo
            'currency' => $this->config['currency'],
            'callback_url' => $this->config[$this->config['environment']]['callback_url'],
        ];
        
        // Add optional parameters
        if (isset($data['reference'])) {
            $payload['reference'] = $data['reference'];
        }
        
        if (isset($data['metadata'])) {
            $payload['metadata'] = $data['metadata'];
        }
        
        if (isset($data['plan_code'])) {
            $payload['plan'] = $data['plan_code'];
        }
        
        $response = $this->makeRequest('POST', $url, $payload);
        
        if ($response['status']) {
            return [
                'success' => true,
                'authorization_url' => $response['data']['authorization_url'],
                'reference' => $response['data']['reference'],
                'access_code' => $response['data']['access_code']
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['message'] ?? 'Transaction initialization failed'
        ];
    }
    
    /**
     * Verify a transaction
     */
    public function verifyTransaction(string $reference): array {
        $url = $this->apiUrl . '/transaction/verify/' . urlencode($reference);
        
        $response = $this->makeRequest('GET', $url);
        
        if ($response['status'] && $response['data']['status'] === 'success') {
            return [
                'success' => true,
                'data' => $response['data']
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['message'] ?? 'Transaction verification failed'
        ];
    }
    
    /**
     * Create a subscription plan
     */
    public function createPlan(array $data): array {
        $url = $this->apiUrl . '/plan';
        
        $payload = [
            'name' => $data['name'],
            'amount' => $data['amount'] * 100, // Convert to kobo
            'interval' => $data['interval'], // 'monthly' or 'yearly'
            'currency' => $this->config['currency'],
        ];
        
        if (isset($data['description'])) {
            $payload['description'] = $data['description'];
        }
        
        $response = $this->makeRequest('POST', $url, $payload);
        
        if ($response['status']) {
            return [
                'success' => true,
                'plan_code' => $response['data']['plan_code'],
                'data' => $response['data']
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['message'] ?? 'Plan creation failed'
        ];
    }
    
    /**
     * Subscribe a customer to a plan
     */
    public function subscribe(array $data): array {
        $url = $this->apiUrl . '/subscription';
        
        $payload = [
            'customer' => $data['customer_code'],
            'plan' => $data['plan_code'],
        ];
        
        if (isset($data['authorization_code'])) {
            $payload['authorization_code'] = $data['authorization_code'];
        }
        
        $response = $this->makeRequest('POST', $url, $payload);
        
        if ($response['status']) {
            return [
                'success' => true,
                'subscription_code' => $response['data']['subscription_code'],
                'data' => $response['data']
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['message'] ?? 'Subscription failed'
        ];
    }
    
    /**
     * Create a customer
     */
    public function createCustomer(array $data): array {
        $url = $this->apiUrl . '/customer';
        
        $payload = [
            'email' => $data['email'],
            'first_name' => $data['first_name'] ?? '',
            'last_name' => $data['last_name'] ?? '',
        ];
        
        if (isset($data['phone'])) {
            $payload['phone'] = $data['phone'];
        }
        
        $response = $this->makeRequest('POST', $url, $payload);
        
        if ($response['status']) {
            return [
                'success' => true,
                'customer_code' => $response['data']['customer_code'],
                'data' => $response['data']
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['message'] ?? 'Customer creation failed'
        ];
    }
    
    /**
     * Make HTTP request to Paystack API
     */
    private function makeRequest(string $method, string $url, array $data = []): array {
        $curl = curl_init();

        $options = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $this->config['callback_timeout'],
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->apiKey,
                'Content-Type: application/json',
                'Cache-Control: no-cache'
            ]
        ];

        if ($method === 'POST') {
            $options[CURLOPT_POST] = true;
            $options[CURLOPT_POSTFIELDS] = json_encode($data);
        }

        curl_setopt_array($curl, $options);

        $response = curl_exec($curl);
        $err = curl_error($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        curl_close($curl);

        // Log request details for debugging
        error_log('Paystack Request - URL: ' . $url);
        error_log('Paystack Request - Method: ' . $method);
        error_log('Paystack Request - HTTP Code: ' . $httpCode);
        error_log('Paystack Request - Key prefix: ' . substr($this->apiKey, 0, 10) . '...');
        error_log('Paystack Request - Response: ' . $response);

        if ($err) {
            error_log('Paystack Curl Error: ' . $err);
            return [
                'status' => false,
                'message' => 'Curl error: ' . $err
            ];
        }

        $result = json_decode($response, true);

        if ($httpCode !== 200) {
            $errorMsg = $result['message'] ?? 'HTTP error: ' . $httpCode;
            error_log('Paystack API Error: ' . $errorMsg);
            return [
                'status' => false,
                'message' => $errorMsg
            ];
        }

        return $result;
    }
    
    /**
     * Get public key for frontend
     */
    public function getPublicKey(): string {
        $env = $this->config['environment'];
        return $this->config[$env]['public_key'];
    }
    
    /**
     * Validate webhook signature
     */
    public function validateWebhook(string $payload, string $signature): bool {
        $env = $this->config['environment'];
        $secret = $this->config[$env]['secret_key'];
        
        $expectedSignature = hash_hmac('sha512', $payload, $secret);
        
        return hash_equals($expectedSignature, $signature);
    }
}
