<?php

/**
 * Payment Manager - Handles Stripe and Razorpay payment processing
 */
class PaymentManager {
    
    private static $stripeSecretKey;
    private static $razorpayKeyId;
    private static $razorpayKeySecret;
    
    public static function initialize(): void {
        // Load configuration
        self::$stripeSecretKey = $_ENV['STRIPE_SECRET_KEY'] ?? 'sk_test_...';
        self::$razorpayKeyId = $_ENV['RAZORPAY_KEY_ID'] ?? 'rzp_test_...';
        self::$razorpayKeySecret = $_ENV['RAZORPAY_KEY_SECRET'] ?? '...';
    }
    
    /**
     * Create Stripe checkout session
     */
    public static function createStripeCheckoutSession(int $planId, string $billingCycle, int $companyId, string $customerEmail): array {
        self::initialize();
        
        $plan = SubscriptionManager::getPlan($planId);
        if (!$plan) {
            throw new Exception('Invalid plan');
        }
        
        $priceId = $billingCycle === 'yearly' ? $plan['stripe_price_id_yearly'] : $plan['stripe_price_id_monthly'];
        
        if (!$priceId) {
            throw new Exception('Price not configured for this plan');
        }
        
        // Create or get Stripe customer
        $customerId = self::getOrCreateStripeCustomer($companyId, $customerEmail);
        
        $checkoutData = [
            'customer' => $customerId,
            'payment_method_types' => ['card'],
            'mode' => 'subscription',
            'line_items' => [
                [
                    'price' => $priceId,
                    'quantity' => 1,
                ],
            ],
            'success_url' => "https://{$companyId}.keelance.com/billing/success?session_id={CHECKOUT_SESSION_ID}",
            'cancel_url' => "https://{$companyId}.keelance.com/billing/cancel",
            'metadata' => [
                'company_id' => $companyId,
                'plan_id' => $planId,
                'billing_cycle' => $billingCycle,
            ],
        ];
        
        // Use Stripe API (would require stripe/stripe-php package)
        // For now, return mock session data
        return [
            'session_id' => 'cs_test_' . uniqid(),
            'url' => "https://checkout.stripe.com/pay/cs_test_" . uniqid(),
            'customer_id' => $customerId
        ];
    }
    
    /**
     * Create Razorpay payment link
     */
    public static function createRazorpayPaymentLink(int $planId, string $billingCycle, int $companyId, string $customerEmail): array {
        self::initialize();
        
        $plan = SubscriptionManager::getPlan($planId);
        if (!$plan) {
            throw new Exception('Invalid plan');
        }
        
        $amount = $billingCycle === 'yearly' ? $plan['price_yearly'] : $plan['price_monthly'];
        $amountInPaise = (int)($amount * 100); // Convert to paise
        
        // Create or get Razorpay customer
        $customerId = self::getOrCreateRazorpayCustomer($companyId, $customerEmail);
        
        $paymentLinkData = [
            'amount' => $amountInPaise,
            'currency' => 'INR',
            'accept_partial' => false,
            'description' => "{$plan['name']} Plan - " . ucfirst($billingCycle),
            'customer' => [
                'name' => $customerEmail,
                'email' => $customerEmail,
            ],
            'notify' => [
                'sms' => true,
                'email' => true
            ],
            'reminder_enable' => true,
            'notes' => [
                'company_id' => $companyId,
                'plan_id' => $planId,
                'billing_cycle' => $billingCycle,
            ],
            'callback_url' => "https://{$companyId}.keelance.com/billing/razorpay-callback",
            'callback_method' => 'get'
        ];
        
        // Use Razorpay API (would require razorpay/razorpay package)
        // For now, return mock payment link
        return [
            'id' => 'plink_' . uniqid(),
            'short_url' => "https://rzp.io/i/" . uniqid(),
            'amount' => $amountInPaise,
            'customer_id' => $customerId
        ];
    }
    
    /**
     * Get or create Stripe customer
     */
    private static function getOrCreateStripeCustomer(int $companyId, string $email): string {
        $pdo = getPDO();
        
        // Check if customer already exists
        $stmt = $pdo->prepare("SELECT stripe_customer_id FROM companies WHERE id = ?");
        $stmt->execute([$companyId]);
        $company = $stmt->fetch();
        
        if ($company && $company['stripe_customer_id']) {
            return $company['stripe_customer_id'];
        }
        
        // Create new customer
        $customerId = 'cus_' . uniqid();
        
        // Update company with customer ID
        $updateStmt = $pdo->prepare("UPDATE companies SET stripe_customer_id = ? WHERE id = ?");
        $updateStmt->execute([$customerId, $companyId]);
        
        return $customerId;
    }
    
    /**
     * Get or create Razorpay customer
     */
    private static function getOrCreateRazorpayCustomer(int $companyId, string $email): string {
        $pdo = getPDO();
        
        // Check if customer already exists
        $stmt = $pdo->prepare("SELECT razorpay_customer_id FROM companies WHERE id = ?");
        $stmt->execute([$companyId]);
        $company = $stmt->fetch();
        
        if ($company && $company['razorpay_customer_id']) {
            return $company['razorpay_customer_id'];
        }
        
        // Create new customer
        $customerId = 'cust_' . uniqid();
        
        // Update company with customer ID
        $updateStmt = $pdo->prepare("UPDATE companies SET razorpay_customer_id = ? WHERE id = ?");
        $updateStmt->execute([$customerId, $companyId]);
        
        return $customerId;
    }
    
    /**
     * Process Stripe webhook
     */
    public static function processStripeWebhook(): bool {
        $payload = file_get_contents('php://input');
        $sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
        
        // Verify webhook signature (would require Stripe secret)
        // For now, process directly
        
        $event = json_decode($payload, true);
        
        if (!$event) {
            return false;
        }
        
        return SubscriptionManager::processWebhook('stripe', $event);
    }
    
    /**
     * Process Razorpay webhook
     */
    public static function processRazorpayWebhook(): bool {
        $payload = file_get_contents('php://input');
        
        // Verify webhook signature (would require Razorpay secret)
        // For now, process directly
        
        $event = json_decode($payload, true);
        
        if (!$event) {
            return false;
        }
        
        return SubscriptionManager::processWebhook('razorpay', $event);
    }
    
    /**
     * Get payment methods for company
     */
    public static function getPaymentMethods(int $companyId): array {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare("
            SELECT * FROM payment_methods 
            WHERE company_id = ? 
            ORDER BY is_default DESC, created_at DESC
        ");
        
        $stmt->execute([$companyId]);
        return $stmt->fetchAll();
    }
    
    /**
     * Add payment method (Stripe)
     */
    public static function addStripePaymentMethod(int $companyId, string $paymentMethodId): bool {
        $pdo = getPDO();
        
        // Get payment method details from Stripe (mock for now)
        $paymentDetails = [
            'type' => 'card',
            'last_four' => '4242',
            'brand' => 'visa',
            'expires_month' => 12,
            'expires_year' => 2025
        ];
        
        $stmt = $pdo->prepare("
            INSERT INTO payment_methods 
            (company_id, type, stripe_payment_method_id, last_four, brand, expires_month, expires_year)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        ");
        
        return $stmt->execute([
            $companyId,
            $paymentDetails['type'],
            $paymentMethodId,
            $paymentDetails['last_four'],
            $paymentDetails['brand'],
            $paymentDetails['expires_month'],
            $paymentDetails['expires_year']
        ]);
    }
    
    /**
     * Set default payment method
     */
    public static function setDefaultPaymentMethod(int $companyId, int $paymentMethodId): bool {
        $pdo = getPDO();
        $pdo->beginTransaction();
        
        try {
            // Remove default flag from all methods
            $unsetStmt = $pdo->prepare("
                UPDATE payment_methods 
                SET is_default = 0 
                WHERE company_id = ?
            ");
            $unsetStmt->execute([$companyId]);
            
            // Set new default
            $setStmt = $pdo->prepare("
                UPDATE payment_methods 
                SET is_default = 1 
                WHERE id = ? AND company_id = ?
            ");
            $setStmt->execute([$paymentMethodId, $companyId]);
            
            $pdo->commit();
            return true;
            
        } catch (Exception $e) {
            $pdo->rollback();
            return false;
        }
    }
    
    /**
     * Delete payment method
     */
    public static function deletePaymentMethod(int $companyId, int $paymentMethodId): bool {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare("
            DELETE FROM payment_methods 
            WHERE id = ? AND company_id = ? AND is_default = 0
        ");
        
        return $stmt->execute([$paymentMethodId, $companyId]);
    }
    
    /**
     * Create customer portal session (Stripe)
     */
    public static function createCustomerPortalSession(int $companyId): array {
        $company = SubscriptionManager::getCompanySubscription($companyId);
        
        if (!$company || !$company['stripe_customer_id']) {
            throw new Exception('No Stripe customer found');
        }
        
        // Create portal session (would require Stripe API)
        return [
            'url' => "https://billing.stripe.com/session/" . uniqid()
        ];
    }
    
    /**
     * Calculate proration for plan upgrade/downgrade
     */
    public static function calculateProration(int $companyId, int $newPlanId, string $newBillingCycle): array {
        $currentSubscription = SubscriptionManager::getCompanySubscription($companyId);
        $newPlan = SubscriptionManager::getPlan($newPlanId);
        
        if (!$currentSubscription || !$newPlan) {
            throw new Exception('Invalid subscription or plan');
        }
        
        $currentPrice = $currentSubscription['billing_cycle'] === 'yearly' 
            ? $currentSubscription['price_yearly'] 
            : $currentSubscription['price_monthly'];
            
        $newPrice = $newBillingCycle === 'yearly' 
            ? $newPlan['price_yearly'] 
            : $newPlan['price_monthly'];
        
        // Simple proration calculation (would be more complex in reality)
        $daysInPeriod = $newBillingCycle === 'yearly' ? 365 : 30;
        $daysRemaining = $daysInPeriod; // Simplified
        
        $prorationRatio = $daysRemaining / $daysInPeriod;
        $proratedAmount = ($newPrice - $currentPrice) * $prorationRatio;
        
        return [
            'current_price' => $currentPrice,
            'new_price' => $newPrice,
            'prorated_amount' => max(0, $proratedAmount),
            'total_due' => $newPrice + max(0, $proratedAmount)
        ];
    }
}
