<?php
namespace PaymentGateway;

use PDO;
use Exception;

abstract class BaseGateway
{
    protected $config;
    protected $conn;
    
    public function __construct($config, $conn)
    {
        $this->config = $config;
        $this->conn = $conn;
    }
    
    /**
     * Process a payment
     * 
     * @param array $data Payment data including amount, user_id, etc.
     * @return array Result with success status and redirect_url or error message
     */
    abstract public function processPayment($data);
    
    /**
     * Handle webhook from payment provider
     * 
     * @return array Result with success status and message
     */
    abstract public function handleWebhook();
    
    /**
     * Verify a payment
     * 
     * @param string $paymentId
     * @return array Payment status and details
     */
    abstract public function verifyPayment($paymentId);
    
    /**
     * Get gateway configuration fields
     * 
     * @return array Configuration fields for admin panel
     */
    abstract public function getConfigFields();
    
    /**
     * Test gateway connection
     * 
     * @return array Test result
     */
    abstract public function testConnection();
    
    /**
     * Update payment status in database
     * 
     * @param int $paymentId
     * @param string $status
     * @param array $details
     * @return bool
     */
    protected 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;
        }
    }
    
    /**
     * Get payment details from database
     * 
     * @param int $paymentId
     * @return array|null
     */
    protected 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;
        }
    }
    
    /**
     * Process subscription renewal after successful payment
     * 
     * @param int $subscriptionId
     * @param int $paymentId
     * @return bool
     */
    protected function processSubscriptionRenewal($subscriptionId, $paymentId)
    {
        try {
            // Get subscription details
            $sql = "SELECT * FROM subscriptions WHERE id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$subscriptionId]);
            $subscription = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$subscription) {
                return false;
            }
            
            // Calculate new expiry date
            $currentExpiry = $subscription['expires_at'];
            $now = date('Y-m-d H:i:s');
            
            // If subscription is already expired, start from now
            $startDate = (strtotime($currentExpiry) > time()) ? $currentExpiry : $now;
            
            // Add billing period (assuming monthly for now)
            $newExpiry = date('Y-m-d H:i:s', strtotime($startDate . ' +1 month'));
            
            // Update subscription
            $sql = "UPDATE subscriptions SET 
                    status = 'active', 
                    expires_at = ?, 
                    last_payment_id = ?,
                    updated_at = NOW() 
                    WHERE id = ?";
            $stmt = $this->conn->prepare($sql);
            $result = $stmt->execute([$newExpiry, $paymentId, $subscriptionId]);
            
            if ($result) {
                // Log renewal
                $sql = "INSERT INTO subscription_renewals (subscription_id, payment_id, previous_expiry, new_expiry, created_at) 
                        VALUES (?, ?, ?, ?, NOW())";
                $stmt = $this->conn->prepare($sql);
                $stmt->execute([$subscriptionId, $paymentId, $currentExpiry, $newExpiry]);
            }
            
            return $result;
            
        } catch (Exception $e) {
            error_log("Subscription renewal error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Send payment notification email
     * 
     * @param int $paymentId
     * @param string $status
     * @return bool
     */
    protected function sendPaymentNotification($paymentId, $status)
    {
        try {
            // Get payment and user details
            $sql = "SELECT p.*, u.email, u.fullname 
                    FROM payments p 
                    JOIN users u ON p.user_id = u.id 
                    WHERE p.id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([$paymentId]);
            $payment = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$payment) {
                return false;
            }
            
            // Prepare email content based on status
            $subject = '';
            $message = '';
            
            switch ($status) {
                case 'completed':
                    $subject = 'Payment Confirmation - Subscription Renewed';
                    $message = "Dear {$payment['fullname']},\n\n";
                    $message .= "Your payment of $" . number_format($payment['amount'], 2) . " has been successfully processed.\n";
                    $message .= "Your subscription has been renewed and is now active.\n\n";
                    $message .= "Payment ID: {$paymentId}\n";
                    $message .= "Amount: $" . number_format($payment['amount'], 2) . "\n";
                    $message .= "Date: " . date('Y-m-d H:i:s') . "\n\n";
                    $message .= "Thank you for your business!\n\n";
                    $message .= "Best regards,\nNuxSaaS Team";
                    break;
                    
                case 'failed':
                    $subject = 'Payment Failed - Action Required';
                    $message = "Dear {$payment['fullname']},\n\n";
                    $message .= "We were unable to process your payment of $" . number_format($payment['amount'], 2) . ".\n";
                    $message .= "Please check your payment method and try again.\n\n";
                    $message .= "Payment ID: {$paymentId}\n";
                    $message .= "Amount: $" . number_format($payment['amount'], 2) . "\n";
                    $message .= "Date: " . date('Y-m-d H:i:s') . "\n\n";
                    $message .= "If you continue to experience issues, please contact our support team.\n\n";
                    $message .= "Best regards,\nNuxSaaS Team";
                    break;
            }
            
            if ($subject && $message) {
                // Send email (implement your email sending logic here)
                mail($payment['email'], $subject, $message);
            }
            
            return true;
            
        } catch (Exception $e) {
            error_log("Payment notification error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Generate secure hash for payment verification
     * 
     * @param array $data
     * @param string $secret
     * @return string
     */
    protected function generateHash($data, $secret)
    {
        ksort($data);
        $string = '';
        foreach ($data as $key => $value) {
            $string .= $key . '=' . $value . '&';
        }
        $string = rtrim($string, '&');
        return hash_hmac('sha256', $string, $secret);
    }
    
    /**
     * Validate webhook signature
     * 
     * @param string $payload
     * @param string $signature
     * @param string $secret
     * @return bool
     */
    protected function validateSignature($payload, $signature, $secret)
    {
        $expectedSignature = hash_hmac('sha256', $payload, $secret);
        return hash_equals($expectedSignature, $signature);
    }
}
