<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\User;
use App\Services\MLMRigourousService;
use App\Services\EmailService;
use App\Services\PdfService;
use App\Services\AMMService;
use App\Services\NotificationService;
use App\Services\Payment\PaymentGatewayManager;
use App\Helpers\RoleHelper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    protected $pdfService;
    protected PaymentGatewayManager $paymentManager;
    protected AMMService $ammService;

    public function __construct(PaymentGatewayManager $paymentManager, PdfService $pdfService, AMMService $ammService)
    {
        $this->paymentManager = $paymentManager;
        $this->pdfService = $pdfService;
        $this->ammService = $ammService;
    }

    /**
     * Initialiser le paiement d'abonnement MLM via Flutterwave
     */
    public function initSubscription(Request $request)
    {
        try {
            if (!Auth::check() || !RoleHelper::canAccessMemberArea(Auth::user()->role)) {
                return redirect()->route('member.login')->with('error', 'Veuillez vous connecter en tant que membre.');
            }

            $user = Auth::user();

            // Montant d'abonnement depuis les paramètres (fallback 5000 XOF)
            $amount = (float) (\App\Models\Setting::get('subscription_price', 5000));
            $currency = config('payment.currencies.' . ($user->country_code ?? 'BJ')) ?? 'XOF';

            $txRef = 'SUB-' . strtoupper(uniqid()) . '-' . $user->id;

            $payload = [
                'tx_ref' => $txRef,
                'amount' => $amount,
                'currency' => $currency,
                'redirect_url' => route('subscription.callback'),
                'customer_email' => $user->email,
                'customer_phone' => $user->phone,
                'customer_name' => $user->full_name ?? ($user->name ?? 'Membre'),
                'description' => 'Abonnement MLM - Activation accès LesWac',
                'meta' => [
                    'purpose' => 'subscription',
                    'user_id' => $user->id,
                ],
            ];

            $result = $this->paymentManager->initiate($payload);

            if (!$result['success']) {
                return redirect()->route('member.dashboard')->with('error', $result['error'] ?? 'Impossible d\'initialiser le paiement.');
            }

            // Mémoriser les attentes pour la vérification
            session([
                'subscription_expected_amount' => $amount,
                'subscription_tx_ref' => $result['tx_ref'] ?? $txRef,
            ]);

            return redirect()->away($result['authorization_url']);
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error('Subscription init error', ['error' => $e->getMessage()]);
            return redirect()->route('member.dashboard')->with('error', 'Erreur: ' . $e->getMessage());
        }
    }

    /**
     * Callback après paiement Flutterwave
     */
    public function callback(Request $request)
    {
        $txRef = $request->query('tx_ref');
        $status = $request->query('status');

        Log::info('Payment callback received', [
            'tx_ref' => $txRef,
            'status' => $status,
            'ip' => $request->ip(),
        ]);

        if (!$txRef) {
            Log::error('Payment callback missing tx_ref');
            return redirect()->route('cart.index')->with('error', 'Référence de transaction manquante.');
        }

        try {
            // Vérifier le paiement auprès du gateway
            $verificationResult = $this->paymentManager->verify($txRef);

            if (!$verificationResult['success']) {
                Log::error('Payment verification failed', [
                    'tx_ref' => $txRef,
                    'error' => $verificationResult['error'] ?? 'Unknown error',
                ]);
                return redirect()->route('cart.index')->with('error', 'Paiement non confirmé. ' . ($verificationResult['error'] ?? ''));
            }

            // Récupérer les données de session
            $cart = session('cart', []);
            $checkoutData = session('checkout_data', []);

            if (empty($checkoutData) || empty($cart) || !is_array($checkoutData)) {
                Log::warning('Payment verified but session data missing', [
                    'tx_ref' => $txRef,
                    'has_checkout_data' => !empty($checkoutData),
                    'has_cart' => !empty($cart),
                ]);
                return redirect()->route('cart.index')->with('error', 'Données de commande manquantes.');
            }

            // Calculer le sous-total
            $subtotal = 0;
            foreach ($cart as $item) {
                $subtotal += floatval($item['price']) * intval($item['quantity']);
            }

            // Calculer la réduction
            $discount = 0;
            $discountPercentage = 0;
            $memberCode = session()->get('member_discount_code');
            if ($memberCode) {
                $member = \App\Models\User::where('member_code', $memberCode)->first();
                if ($member && $member->discount_percentage > 0) {
                    $discountPercentage = $member->discount_percentage;
                    $discount = ($subtotal * $discountPercentage) / 100;
                }
            }

            // Utiliser les frais de livraison de la session
            $shippingFee = floatval(session('shipping_fee', $checkoutData['shipping_fee'] ?? 0));

            // Calculer le total final
            $grandTotal = $subtotal + $shippingFee - $discount;

            // Vérifier que le montant payé correspond au total
            if (abs(floatval($verificationResult['amount']) - $grandTotal) > 1) {
                Log::error('Payment amount mismatch', [
                    'expected' => $grandTotal,
                    'received' => $verificationResult['amount'],
                    'tx_ref' => $txRef,
                ]);
                return redirect()->route('cart.index')->with('error', 'Montant du paiement incorrect.');
            }

            // Obtenir l'ID utilisateur si connecté
            $userId = Auth::check() && Auth::user()->role === 'member' ? Auth::id() : null;

            // Déterminer la méthode de paiement réelle (carte ou mobile money)
            $paymentMethod = strtolower($verificationResult['payment_data']['payment_type'] ?? $verificationResult['payment_type'] ?? 'flutterwave');

            // Créer la commande
            $order = Order::create([
                'user_id' => $userId,
                'order_number' => 'ORD-' . strtoupper(uniqid()),
                'customer_name' => ($checkoutData['first_name'] ?? '') . ' ' . ($checkoutData['last_name'] ?? ''),
                'customer_email' => $checkoutData['email'] ?? '',
                'customer_phone' => $checkoutData['phone'] ?? '',
                'shipping_address' => $checkoutData['address'] ?? '',
                'shipping_city' => $checkoutData['city'] ?? '',
                'shipping_country' => $checkoutData['country'] ?? '',
                'shipping_district' => $checkoutData['district'] ?? '',
                'shipping_fee' => $shippingFee,
                'discount_amount' => $discount,
                'discount_percentage' => $discountPercentage,
                'total_amount' => $grandTotal,
                'total' => $grandTotal,
                'subtotal' => $subtotal,
                'payment_status' => 'paid',
                'payment_method' => $paymentMethod,
                'payment_reference' => $txRef,
                'payment_gateway_response' => json_encode($verificationResult),
                'status' => 'pending',
                'order_type' => 'regular',
            ]);

            Log::info('Order created after payment', [
                'order_id' => $order->id,
                'order_number' => $order->order_number,
                'tx_ref' => $txRef,
                'total' => $grandTotal,
            ]);

            // Notification de commande pour le membre
            if ($userId) {
                NotificationService::productPurchased($userId, $order->order_number, $grandTotal, count($cart));
            }

            // ===== DÉTECTION PRODUIT D'INVESTISSEMENT =====
            // Si l'utilisateur est connecté et paie son produit d'investissement
            $investmentService = new \App\Services\InvestmentProductService();
            if ($userId && $order->notes && str_contains($order->notes, 'investissement')) {
                $investmentService->markInvestmentProductAsPaid(Auth::user(), $order);
            }

            // Créer les articles de la commande ET décrémenter le stock
            foreach ($cart as $item) {
                // Récupérer le produit pour avoir le seller_id
                $product = Product::find($item['id']);
                
                OrderItem::create([
                    'order_id' => $order->id,
                    'product_id' => $item['id'],
                    'product_name' => $item['name'],
                    'quantity' => $item['quantity'],
                    'price' => $item['price'],
                    'subtotal' => $item['price'] * $item['quantity'],
                    'unit_price' => $item['price'],
                    'total_price' => $item['price'] * $item['quantity'],
                ]);

                // Décrémenter le stock du produit
                if ($product) {
                    $product->decrement('stock', $item['quantity']);
                }
            }

            // === TRAITER LES PRODUITS SELLER ===
            // Attribuer seller_id, calculer commissions et créditer les wallets des sellers
            $sellerOrderService = new \App\Services\SellerOrderService();
            $sellerResults = $sellerOrderService->processSellerItems($order);
            
            Log::info('Seller items processed', [
                'order_id' => $order->id,
                'seller_items' => $sellerResults['total_seller_items'],
                'seller_amount' => $sellerResults['total_seller_amount'],
                'platform_commission' => $sellerResults['total_platform_commission']
            ]);

            // Calculer les commissions MLM
            if ($userId) {
                // Cas 1: achat par un membre identifié => calcule via l'arbre de parrainage
                $mlmService = new MLMRigourousService();
                $mlmService->updateMonthlySalesAndCheckAMM($order);
                $mlmService->calculateAndCreditMLMCommissions($order);
                
                // === VÉRIFIER ET APPLIQUER L'AVANCE AMM AUTOMATIQUEMENT ===
                // Si les achats personnels du membre >= AMM requis, valider l'AMM du mois prochain
                $user = \App\Models\User::find($userId);
                if ($user) {
                    $ammAdvanceResult = $this->ammService->checkAndApplyAdvanceAfterPurchase($user);
                    if ($ammAdvanceResult['advance_applied']) {
                        Log::info('AMM Advance applied after Flutterwave purchase', [
                            'user_id' => $userId,
                            'order_id' => $order->id,
                            'new_active_until' => $ammAdvanceResult['new_active_until'],
                        ]);
                    }
                }
            } else {
                // Cas 2: achat invité => attribuer commission au membre dont le code est en session
                $memberCode = session()->get('member_discount_code');
                if ($memberCode) {
                    $sponsor = \App\Models\User::where('member_code', $memberCode)->first();
                    if ($sponsor) {
                        // Utiliser les taux depuis mlm_levels (source unique de vérité)
                        $level1 = \App\Models\MlmLevel::where('level', 1)->where('is_active', true)->first();
                        $level2 = \App\Models\MlmLevel::where('level', 2)->where('is_active', true)->first();
                        $level1Rate = $level1 ? floatval($level1->commission_rate) : 10;
                        $level2Rate = $level2 ? floatval($level2->commission_rate) : 5;

                        // Commission niveau 1 (vente invitée via lien du sponsor)
                        // Vérifier subscription_paid pour les ventes invitées aussi
                        $level1Amount = ($order->total_amount * $level1Rate) / 100;
                        if ($level1Amount > 0 && $sponsor->is_active && ($sponsor->subscription_paid || $sponsor->has_paid_investment_product)) {
                            $commission = \App\Models\Commission::create([
                                'user_id' => $sponsor->id,
                                'order_id' => $order->id,
                                'from_user_id' => null,
                                'type' => 'level1',
                                'level' => 1,
                                'amount' => $level1Amount,
                                'status' => 'pending',
                                'description' => 'Commission directe (N1) - Vente invité via ' . $sponsor->name . ' - Commande #' . $order->order_number,
                            ]);
                            // Créditer le portefeuille
                            try {
                                (new \App\Services\WalletService())->credit($sponsor, $level1Amount, 'commission', 'Commission directe (N1) - Vente invité', ['commission_id' => $commission->id, 'order_id' => $order->id]);
                                $commission->update(['status' => 'approved']);
                            } catch (\Exception $e) {
                                \Illuminate\Support\Facades\Log::warning('Wallet credit fallback (guest sale)', ['error' => $e->getMessage()]);
                                $sponsor->increment('total_commissions', $level1Amount);
                                $sponsor->increment('available_balance', $level1Amount);
                            }
                        }

                        // Commission niveau 2 (au parrain du sponsor si applicable)
                        if ($sponsor->sponsor_id) {
                            $superSponsor = \App\Models\User::find($sponsor->sponsor_id);
                            if ($superSponsor && $superSponsor->is_active && ($superSponsor->subscription_paid || $superSponsor->has_paid_investment_product)) {
                                $level2Amount = ($order->total_amount * $level2Rate) / 100;
                                if ($level2Amount > 0) {
                                    $commission2 = \App\Models\Commission::create([
                                        'user_id' => $superSponsor->id,
                                        'order_id' => $order->id,
                                        'from_user_id' => null,
                                        'type' => 'level2',
                                        'level' => 2,
                                        'amount' => $level2Amount,
                                        'status' => 'pending',
                                        'description' => 'Commission indirecte (N2) - Vente invité via équipe de ' . $sponsor->name . ' - Commande #' . $order->order_number,
                                    ]);
                                    try {
                                        (new \App\Services\WalletService())->credit($superSponsor, $level2Amount, 'commission', 'Commission indirecte (N2) - Vente invité', ['commission_id' => $commission2->id, 'order_id' => $order->id]);
                                        $commission2->update(['status' => 'approved']);
                                    } catch (\Exception $e) {
                                        \Illuminate\Support\Facades\Log::warning('Wallet credit fallback (guest sale L2)', ['error' => $e->getMessage()]);
                                        $superSponsor->increment('total_commissions', $level2Amount);
                                        $superSponsor->increment('available_balance', $level2Amount);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Envoyer l'email de confirmation
            EmailService::sendPurchaseConfirmation($order->customer_email, [
                'customer_name' => $order->customer_name,
                'order_number' => $order->order_number,
                'total_amount' => number_format($order->total_amount, 0, ',', ' '),
                'order_date' => $order->created_at->format('d/m/Y à H:i'),
            ]);

            // Nettoyer la session
            session()->forget(['cart', 'checkout_data', 'member_discount_code', 'shipping_fee', 'shipping_country', 'shipping_city', 'shipping_district']);

            Log::info('Payment successful and order completed', [
                'order_id' => $order->id,
                'tx_ref' => $txRef,
            ]);

            return redirect()->route('payment.success', ['order_id' => $order->id])->with('success', 'Paiement effectué avec succès !');
        } catch (\Exception $e) {
            Log::error('Payment processing error', [
                'tx_ref' => $txRef,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return redirect()->route('payment.error', ['reason' => urlencode($e->getMessage())]);
        }
    }

    /**
     * Callback après paiement d'abonnement MLM
     */
    public function subscriptionCallback(Request $request)
    {
        $txRef = $request->query('tx_ref');
        $status = $request->query('status');

        \Illuminate\Support\Facades\Log::info('Subscription callback received', [
            'tx_ref' => $txRef,
            'status' => $status,
            'ip' => $request->ip(),
        ]);

        if (!$txRef) {
            return redirect()->route('member.dashboard')->with('error', 'Référence de transaction manquante.');
        }

        try {
            $verificationResult = $this->paymentManager->verify($txRef);

            if (!$verificationResult['success']) {
                return redirect()->route('member.dashboard')->with('error', 'Paiement non confirmé. ' . ($verificationResult['error'] ?? ''));
            }

            $expected = (float) (session('subscription_expected_amount', \App\Models\Setting::get('subscription_price', 5000)));
            $paid = (float) ($verificationResult['amount'] ?? 0);

            if (abs($paid - $expected) > 1) {
                \Illuminate\Support\Facades\Log::error('Subscription amount mismatch', [
                    'expected' => $expected,
                    'received' => $paid,
                    'tx_ref' => $txRef,
                ]);
                return redirect()->route('member.dashboard')->with('error', 'Montant du paiement incorrect.');
            }

            if (!\Illuminate\Support\Facades\Auth::check()) {
                return redirect()->route('member.login')->with('success', 'Paiement confirmé. Connectez-vous pour activer votre abonnement.');
            }

            $user = \Illuminate\Support\Facades\Auth::user();
            $user->subscription_paid = true;
            $user->subscription_paid_at = now();
            
            // Activer aussi le membre si pas déjà actif
            if (!$user->is_active) {
                $user->is_active = true;
            }
            
            $user->save();

            // Appliquer l'exonération AMM pour le mois en cours (+ mois suivant si après le 16)
            $this->ammService->applySubscriptionExemption($user);

            // ===== BONUS DÉMARRAGE RAPIDE =====
            // Attribuer le bonus de démarrage au parrain lorsque le filleul paie son abonnement
            if ($user->sponsor_id) {
                try {
                    $mlmService = new MLMRigourousService();
                    $startupCommission = $mlmService->giveQuickStartBonusOnSubscriptionPayment($user);
                    
                    if ($startupCommission) {
                        \Illuminate\Support\Facades\Log::info('Commission démarrage attribuée au parrain', [
                            'sponsor_id' => $user->sponsor_id,
                            'new_member_id' => $user->id,
                            'amount' => $startupCommission->amount
                        ]);
                    }
                } catch (\Exception $e) {
                    \Illuminate\Support\Facades\Log::error('Erreur attribution commission démarrage', [
                        'user_id' => $user->id,
                        'sponsor_id' => $user->sponsor_id,
                        'error' => $e->getMessage()
                    ]);
                }
            }

            // Nettoyer session
            session()->forget(['subscription_expected_amount', 'subscription_tx_ref']);
            // Générer le PDF d'abonnement
            try {
                $pdfPath = $this->pdfService->generateSubscriptionPdf($user);
                \Illuminate\Support\Facades\Log::info('PDF abonnement généré', [
                    'user_id' => $user->id,
                    'pdf_path' => $pdfPath
                ]);
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error('Erreur génération PDF abonnement', [
                    'user_id' => $user->id,
                    'error' => $e->getMessage()
                ]);
            }


            // Envoyer une confirmation basique (optionnel)
            try {
                \App\Services\EmailService::sendRaw(
                    $user->email,
                    'Abonnement MLM activé',
                    '<p>Bonjour ' . ($user->full_name ?? $user->name) . ',</p><p>Votre abonnement MLM a été activé avec succès. Vous avez désormais accès aux fonctionnalités MLM.</p><p>Votre certificat d\'abonnement a été généré et est disponible dans votre tableau de bord.</p>'
                );
            } catch (\Exception $e) {
                // Ignorer les erreurs email
            }

            return redirect()->route('member.dashboard')->with('success', 'Abonnement activé avec succès. Accès MLM débloqué.');
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error('Subscription processing error', [
                'tx_ref' => $txRef,
                'error' => $e->getMessage(),
            ]);
            return redirect()->route('member.dashboard')->with('error', $e->getMessage());
        }
    }

    /**
     * Initialiser le paiement de commande boutique via Flutterwave
     */
    public function initOrderPayment(Request $request)
    {
        try {
            $cart = session('cart', []);
            $checkoutData = session('checkout_data', []);

            if (empty($cart) || empty($checkoutData)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Panier ou données de livraison manquants'
                ], 400);
            }

            // Calculer le sous-total
            $subtotal = 0;
            foreach ($cart as $item) {
                $subtotal += floatval($item['price']) * intval($item['quantity']);
            }

            // Calculer la réduction
            $discount = 0;
            $memberCode = session()->get('member_discount_code');
            if ($memberCode) {
                $member = User::where('member_code', $memberCode)->first();
                if ($member && $member->discount_percentage > 0) {
                    $memberDiscount = floatval(\App\Models\Setting::get('member_discount_percentage', 5));
                    $discount = ($subtotal * $memberDiscount) / 100;
                }
            }

            // Frais de livraison
            $shippingFee = floatval(session('shipping_fee', $checkoutData['shipping_fee'] ?? 0));

            // Total
            $grandTotal = $subtotal + $shippingFee - $discount;

            // Générer tx_ref unique côté serveur
            $txRef = 'ORD-' . strtoupper(uniqid()) . '-' . time();

            // Stocker en session pour vérification
            session([
                'order_tx_ref' => $txRef,
                'order_expected_amount' => $grandTotal,
            ]);

            $payload = [
                'tx_ref' => $txRef,
                'amount' => $grandTotal,
                'currency' => 'XOF',
                'redirect_url' => route('payment.callback'),
                'customer_email' => $checkoutData['email'],
                'customer_phone' => $checkoutData['phone'],
                'customer_name' => ($checkoutData['first_name'] ?? '') . ' ' . ($checkoutData['last_name'] ?? ''),
                'description' => 'Commande boutique - ' . count($cart) . ' produit(s)',
                'meta' => [
                    'purpose' => 'order',
                    'item_count' => count($cart),
                ],
            ];

            $result = $this->paymentManager->initiate($payload);

            if (!$result['success']) {
                return response()->json([
                    'success' => false,
                    'message' => $result['error'] ?? 'Impossible d\'initialiser le paiement'
                ], 500);
            }

            return response()->json([
                'success' => true,
                'tx_ref' => $txRef,
                'authorization_url' => $result['authorization_url'],
                'amount' => $grandTotal
            ]);

        } catch (\Exception $e) {
            Log::error('Order payment init error', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Erreur: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Page de succès après paiement
     */
    public function success(Request $request)
    {
        $orderId = $request->query('order_id');

        if (!$orderId) {
            return redirect()->route('cart.index')->with('error', 'Commande non trouvée.');
        }

        $order = Order::with('items')->find($orderId);

        if (!$order) {
            return redirect()->route('cart.index')->with('error', 'Commande non trouvée.');
        }

        return view('shop.success', compact('order'));
    }

    /**
     * Afficher la page d'erreur de paiement
     */
    public function error(Request $request)
    {
        $reason = $request->query('reason', 'Une erreur est survenue lors du paiement.');
        return view('shop.payment-error', compact('reason'));
    }

    /**
     * Webhook pour les notifications Flutterwave (optionnel)
     */
    public function webhook(Request $request)
    {
        $webhookSecret = config('payment.flutterwave.webhook_secret');

        if (!$webhookSecret) {
            Log::warning('Webhook called but webhook secret not configured');
            return response()->json(['error' => 'Webhook not configured'], 400);
        }

        // Vérifier la signature du webhook
        $signature = $request->header('verif-hash');

        if (!$signature || !$this->verifyFlutterwaveSignature($request->all(), $signature)) {
            Log::warning('Invalid webhook signature detected', [
                'ip' => $request->ip(),
                'header' => $signature,
            ]);
            return response()->json(['error' => 'Invalid signature'], 401);
        }

        $event = $request->input('event');
        $data = $request->input('data');

        Log::info('Flutterwave webhook received', [
            'event' => $event,
            'tx_ref' => $data['tx_ref'] ?? null,
            'amount' => $data['amount'] ?? null,
        ]);

        // Traiter le paiement
        try {
            $result = \App\Services\PaymentService::processFlutterwaveCallback($data);
            
            Log::info('Webhook processed successfully', $result);
            return response()->json($result);
        } catch (\Exception $e) {
            Log::error('Webhook processing error: ' . $e->getMessage());
            return response()->json(['error' => 'Processing error'], 500);
        }
    }

    /**
     * Vérifier la signature Flutterwave
     */
    private function verifyFlutterwaveSignature($payload, $signature)
    {
        $secret = config('payment.flutterwave.webhook_secret');
        $hash = hash_hmac('sha256', json_encode($payload), $secret);
        
        return hash_equals($hash, $signature);
    }

    /**
     * Endpoint pour reconcilier les paiements
     * À appeler via CRON ou manuellement pour vérifier les paiements non-traités
     */
    public function reconciliate(Request $request)
    {
        // Vérifier permission admin
        if (!Auth::check() || !in_array(Auth::user()->role, ['admin', 'sub_admin', 'super_admin'])) {
            abort(403);
        }

        $days = $request->get('days', 1);
        $result = \App\Services\PaymentService::reconciliate($days);

        return response()->json($result);
    }
}
