<?php
/**
 * Payment Controller
 * Handles deposit requests and Marzpay payment callbacks
 */

namespace App\Controller;

use App\Classes\Payment\MarzpayGateway;

class PaymentController {
    protected $db;
    protected $gateway;
    
    public function __construct($db) {
        $this->db = $db;
        $this->gateway = new MarzpayGateway();
    }
    
    /**
     * Initiate a deposit/payment
     */
    public function initiatePayment($userId, $amount, $currency = 'UGX') {
        try {
            // Validate amount
            $minDeposit = $this->getSetting('min_deposit', 5000);
            $maxDeposit = $this->getSetting('max_deposits_per_day', 10000000);
            
            if ($amount < $minDeposit) {
                return ['success' => false, 'error' => "Minimum deposit is $minDeposit $currency"];
            }
            
            if ($amount > $maxDeposit) {
                return ['success' => false, 'error' => "Maximum deposit is $maxDeposit $currency"];
            }
            
            // Get user details
            $userStmt = $this->db->prepare('SELECT email, full_name FROM users WHERE id = ?');
            $userStmt->execute([$userId]);
            $user = $userStmt->fetch(\PDO::FETCH_ASSOC);
            
            if (!$user) {
                return ['success' => false, 'error' => 'User not found'];
            }
            
            // Check daily limit for this user
            $dailyTotal = $this->getDailyDepositTotal($userId);
            $dailyLimit = (int)$this->getSetting('max_deposits_per_day', 100000000);
            
            if ($dailyTotal + $amount > $dailyLimit) {
                return ['success' => false, 'error' => 'Daily deposit limit exceeded'];
            }
            
            // Create payment with Marzpay
            $reference = 'DEP-' . $userId . '-' . time();
            $description = 'Account Deposit - BoostWithKagujje';
            
            $paymentResult = $this->gateway->createPayment(
                $amount,
                $currency,
                $reference,
                $description,
                [
                    'user_id' => $userId,
                    'user_email' => $user['email'],
                    'user_name' => $user['full_name']
                ]
            );
            
            if (!MarzpayGateway::isSuccess($paymentResult)) {
                return ['success' => false, 'error' => MarzpayGateway::getError($paymentResult)];
            }
            
            // Store payment request in database
            $paymentId = 'PAY-' . time() . '-' . $userId;
            
            $stmt = $this->db->prepare('
                INSERT INTO payments 
                (payment_id, user_id, reference, amount, currency, gateway, gateway_reference, status, method)
                VALUES (?, ?, ?, ?, ?, "marzpay", ?, "pending", "deposit")
            ');
            
            $stmt->execute([
                $paymentId,
                $userId,
                $reference,
                $amount,
                $currency,
                $paymentResult['payment_id'] ?? $paymentResult['id'] ?? null
            ]);
            
            return [
                'success' => true,
                'payment_id' => $paymentId,
                'payment_url' => $paymentResult['payment_url'] ?? $paymentResult['url'] ?? null,
                'amount' => $amount,
                'currency' => $currency,
                'message' => 'Payment initiated. Redirecting to payment gateway...'
            ];
            
        } catch (\Exception $e) {
            error_log('Payment Initiation Error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Handle Marzpay callback/webhook
     */
    public function handleMarzpayCallback($payload) {
        try {
            // Verify callback signature
            $verified = $this->gateway->verifyCallback($payload);
            
            if (!$verified['valid']) {
                error_log('Invalid Marzpay callback signature');
                return ['success' => false, 'error' => 'Invalid signature'];
            }
            
            // Extract payment data
            $reference = $payload['reference'] ?? $verified['reference'];
            $status = $payload['status'] ?? $verified['status'];
            $amount = $payload['amount'] ?? $verified['amount'];
            
            // Find payment in database
            $stmt = $this->db->prepare('SELECT * FROM payments WHERE reference = ?');
            $stmt->execute([$reference]);
            $payment = $stmt->fetch(\PDO::FETCH_ASSOC);
            
            if (!$payment) {
                error_log("Payment not found for reference: $reference");
                return ['success' => false, 'error' => 'Payment not found'];
            }
            
            // Store webhook event
            $this->storeWebhookEvent('payment_callback', json_encode($payload), $payment['id']);
            
            // Process based on payment status
            if ($status === 'completed' || $status === 'success') {
                return $this->confirmPayment($payment);
            } elseif ($status === 'failed' || $status === 'cancelled') {
                return $this->failPayment($payment, $payload['reason'] ?? 'Payment failed');
            }
            
            return ['success' => true, 'message' => 'Callback processed'];
            
        } catch (\Exception $e) {
            error_log('Marzpay Callback Error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Confirm payment and credit user account
     */
    private function confirmPayment($payment) {
        try {
            $this->db->beginTransaction();
            
            // Update payment status
            $stmt = $this->db->prepare('UPDATE payments SET status = "completed", paid_at = NOW() WHERE id = ?');
            $stmt->execute([$payment['id']]);
            
            // Get user current balance
            $userStmt = $this->db->prepare('SELECT balance FROM users WHERE id = ?');
            $userStmt->execute([$payment['user_id']]);
            $user = $userStmt->fetch(\PDO::FETCH_ASSOC);
            
            $previousBalance = $user['balance'];
            $newBalance = $previousBalance + $payment['amount'];
            
            // Credit user account
            $creditStmt = $this->db->prepare('UPDATE users SET balance = ? WHERE id = ?');
            $creditStmt->execute([$newBalance, $payment['user_id']]);
            
            // Log transaction
            $transStmt = $this->db->prepare('
                INSERT INTO transactions 
                (user_id, transaction_type, reference_id, description, amount, previous_balance, new_balance, gateway, status)
                VALUES (?, "deposit", ?, ?, ?, ?, ?, "marzpay", "completed")
            ');
            
            $transStmt->execute([
                $payment['user_id'],
                $payment['payment_id'],
                'Deposit via Marzpay',
                $payment['amount'],
                $previousBalance,
                $newBalance
            ]);
            
            $this->db->commit();
            
            // Queue confirmation email
            $this->queuePaymentEmail($payment['user_id'], $payment['amount'], $payment['currency'], 'confirmed');
            
            return [
                'success' => true,
                'message' => 'Payment confirmed and balance credited',
                'payment_id' => $payment['payment_id'],
                'amount' => $payment['amount'],
                'new_balance' => $newBalance
            ];
            
        } catch (\Exception $e) {
            $this->db->rollBack();
            error_log('Payment Confirmation Error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Fail payment
     */
    private function failPayment($payment, $reason) {
        try {
            $stmt = $this->db->prepare('UPDATE payments SET status = "failed", failed_reason = ? WHERE id = ?');
            $stmt->execute([$reason, $payment['id']]);
            
            // Queue failure email
            $this->queuePaymentEmail($payment['user_id'], $payment['amount'], $payment['currency'], 'failed', $reason);
            
            return ['success' => true, 'message' => 'Payment marked as failed'];
            
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Get user's payment history
     */
    public function getPaymentHistory($userId, $limit = 50) {
        try {
            $stmt = $this->db->prepare('
                SELECT * FROM payments
                WHERE user_id = ?
                ORDER BY created_at DESC
                LIMIT ?
            ');
            $stmt->execute([$userId, $limit]);
            $payments = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            
            return ['success' => true, 'payments' => $payments];
            
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Get daily deposit total for user
     */
    private function getDailyDepositTotal($userId) {
        try {
            $stmt = $this->db->prepare('
                SELECT COALESCE(SUM(amount), 0) as total
                FROM payments
                WHERE user_id = ? AND status = "completed" AND DATE(paid_at) = CURDATE()
            ');
            $stmt->execute([$userId]);
            return (float)$stmt->fetch(\PDO::FETCH_ASSOC)['total'];
        } catch (\Exception $e) {
            return 0;
        }
    }
    
    /**
     * Get setting value
     */
    private function getSetting($key, $default = null) {
        try {
            $stmt = $this->db->prepare('SELECT setting_value FROM settings WHERE setting_key = ?');
            $stmt->execute([$key]);
            $result = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $result['setting_value'] ?? $default;
        } catch (\Exception $e) {
            return $default;
        }
    }
    
    /**
     * Store webhook event for debugging
     */
    private function storeWebhookEvent($eventType, $payload, $paymentId = null) {
        try {
            $stmt = $this->db->prepare('
                INSERT INTO webhook_events (event_type, source, payload, created_at)
                VALUES (?, "marzpay", ?, NOW())
            ');
            $stmt->execute([$eventType, $payload]);
        } catch (\Exception $e) {
            error_log('Webhook Event Storage Error: ' . $e->getMessage());
        }
    }
    
    /**
     * Queue payment email notification
     */
    private function queuePaymentEmail($userId, $amount, $currency, $status, $reason = '') {
        try {
            $user = $this->db->query("SELECT email FROM users WHERE id = $userId")->fetch(\PDO::FETCH_ASSOC);
            
            if ($user) {
                $subject = $status === 'confirmed' ? "Deposit Confirmed - $amount $currency" : "Deposit Failed";
                $template = $status === 'confirmed' ? 'payment_confirmed' : 'payment_failed';
                $data = [
                    'amount' => $amount,
                    'currency' => $currency,
                    'status' => $status,
                    'reason' => $reason
                ];
                
                $stmt = $this->db->prepare('
                    INSERT INTO email_queue (recipient, subject, template, data, status)
                    VALUES (?, ?, ?, ?, "pending")
                ');
                $stmt->execute([$user['email'], $subject, $template, json_encode($data)]);
            }
        } catch (\Exception $e) {
            error_log('Payment Email Queue Error: ' . $e->getMessage());
        }
    }
}
?>
