<?php

namespace App\Services;

use App\Models\User;
use App\Models\FeatureToggle;
use App\Models\Order;
use App\Models\Commission;
use App\Models\MonthlySalesTracking;
use App\Models\Setting;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * Service MLM Rigoureux
 * Gère tous les calculs de commissions, bonus, et validations selon les paramètres financiers
 * Centre névralgique du marketing de réseau
 */
class MLMRigourousService
{
    protected $walletService;

    public function __construct()
    {
        $this->walletService = new WalletService();
    }

    /**
     * ===========================================================================
     * 1️⃣  BONUS DÉMARRAGE RAPIDE
     * ===========================================================================
     * ✓ Donné UNIQUEMENT quand le filleul direct paie son abonnement avec succès
     * ✓ Opération atomique : vérifier payment confirmé + créditer parrain
     */
    public function giveQuickStartBonusOnSubscriptionPayment(User $newMember)
    {
        // VÉRIFICATION: Feature toggle pour le bonus démarrage rapide
        if (!FeatureToggle::isEnabled('quick_start_bonus')) {
            Log::info('Quick Start Bonus : désactivé par feature toggle');
            return null;
        }

        if (!$newMember->subscription_paid) {
            Log::warning('Quick Start Bonus : abonnement non payé', [
                'user_id' => $newMember->id,
            ]);
            return null;
        }

        if (!$newMember->sponsor_id) {
            Log::info('Quick Start Bonus : pas de parrain', ['user_id' => $newMember->id]);
            return null;
        }

        return DB::transaction(function () use ($newMember) {
            $sponsor = User::find($newMember->sponsor_id);

            if (!$sponsor) {
                return null;
            }

            // Vérifier que le parrain peut recevoir des commissions
            if (!$this->canReceiveCommissions($sponsor)) {
                Log::warning('Parrain inéligible pour bonus', [
                    'sponsor_id' => $sponsor->id,
                    'reason' => 'inactif ou non abonné',
                ]);
                return null;
            }

            $bonusAmount = floatval(Setting::get('quick_start_bonus', 5000));

            if ($bonusAmount <= 0) {
                return null;
            }

            $commission = Commission::create([
                'user_id' => $sponsor->id,
                'order_id' => null,
                'from_user_id' => $newMember->id,
                'type' => 'quick_start',
                'level' => 0,
                'amount' => $bonusAmount,
                'status' => 'paid',
                'description' => "Bonus démarrage rapide : {$newMember->name} a payé abonnement",
            ]);

            $this->walletService->credit(
                $sponsor,
                $bonusAmount,
                'bonus',
                "Bonus démarrage rapide - {$newMember->name}",
                ['commission_id' => $commission->id, 'new_member_id' => $newMember->id]
            );

            Log::info('✅ Bonus démarrage rapide attribué', [
                'sponsor_id' => $sponsor->id,
                'member_id' => $newMember->id,
                'amount' => $bonusAmount,
            ]);

            return $commission;
        });
    }

    /**
     * ===========================================================================
     * 2️⃣  ACHAT MENSUEL MINIMUM - AMM
     * ===========================================================================
     * ✓ Parrain ET filleul doivent dépenser ce montant chaque mois
     * ✓ Reset à zéro chaque mois
     * ✓ Détermine l'éligibilité aux commissions ce mois-ci
     * ✓ Pour produits d'investissement: comptabilisé dès paiement
     * ✓ Pour produits physiques: comptabilisé à la livraison
     */
    public function updateMonthlySalesAndCheckAMM(Order $order)
    {
        // LOGIQUE CORRIGÉE: Comptabiliser l'AMM dès que le paiement est confirmé
        // Peu importe le type de commande, si c'est payé, ça compte pour l'AMM
        $canCountForAMM = ($order->payment_status === 'paid');

        if (!$canCountForAMM) {
            Log::debug('AMM : Commande pas encore comptabilisable', [
                'order_id' => $order->id,
                'order_type' => $order->order_type,
                'payment_status' => $order->payment_status,
                'status' => $order->status,
                'reason' => 'Paiement non confirmé'
            ]);
            return;
        }

        return DB::transaction(function () use ($order) {
            $user = $order->user;
            
            if (!$user) {
                Log::warning('AMM : Pas d\'utilisateur pour cette commande', ['order_id' => $order->id]);
                return;
            }

            try {
                $ammRequired = floatval(Setting::get('minimum_monthly_purchase', 50000));

                // Récupérer ou créer le suivi mensuel de l'acheteur
                $monthlyTracking = MonthlySalesTracking::where('user_id', $user->id)
                    ->where('month', now()->format('Y-m'))
                    ->first();

                if (!$monthlyTracking) {
                    $monthlyTracking = MonthlySalesTracking::create([
                        'user_id' => $user->id,
                        'month' => now()->format('Y-m'),
                        'total_purchase_amount' => 0,
                        'has_met_amm' => false,
                        'is_eligible_for_commissions' => false,
                    ]);
                }

                $previousAmount = $monthlyTracking->total_purchase_amount;
                $monthlyTracking->increment('total_purchase_amount', $order->total_amount);
                $monthlyTracking->refresh();

                // Vérifier si l'AMM est atteint ce mois-ci
                if ($monthlyTracking->total_purchase_amount >= $ammRequired) {
                    $monthlyTracking->update(['has_met_amm' => true, 'is_eligible_for_commissions' => true]);

                    Log::info('✅ AMM atteint ce mois', [
                        'user_id' => $user->id,
                        'user_name' => $user->name,
                        'previous_amount' => $previousAmount,
                        'order_amount' => $order->total_amount,
                        'new_total' => $monthlyTracking->total_purchase_amount,
                        'required_amm' => $ammRequired,
                        'surplus' => $monthlyTracking->total_purchase_amount - $ammRequired,
                    ]);
                } else {
                    Log::info('⏳ AMM partiel ce mois', [
                        'user_id' => $user->id,
                        'user_name' => $user->name,
                        'current_amount' => $monthlyTracking->total_purchase_amount,
                        'required_amm' => $ammRequired,
                        'remaining' => $ammRequired - $monthlyTracking->total_purchase_amount,
                    ]);
                }
            } catch (\Exception $e) {
                Log::error('Erreur lors de la mise à jour du suivi mensuel', [
                    'user_id' => $user->id,
                    'order_id' => $order->id,
                    'error' => $e->getMessage(),
                ]);
            }
        });
    }

    /**
     * ===========================================================================
     * 3️⃣  RÉDUCTION MEMBRE
     * ===========================================================================
     * ✓ % de réduction appliqué quand un membre achète LUI-MÊME
     * ✓ % de réduction appliqué quand quelqu'un utilise le code membre pour acheter
     * Appliqué au TOTAL de la commande
     */
    public function calculateMemberDiscount($baseAmount, User $member = null): array
    {
        $discountPercentage = floatval(Setting::get('member_discount_percentage', 5));

        if (!$member || $discountPercentage <= 0) {
            return [
                'original_amount' => $baseAmount,
                'discount_amount' => 0,
                'final_amount' => $baseAmount,
                'discount_percentage' => 0,
            ];
        }

        $discountAmount = ($baseAmount * $discountPercentage) / 100;
        $finalAmount = $baseAmount - $discountAmount;

        Log::info('✅ Réduction membre appliquée', [
            'member_id' => $member->id,
            'original' => $baseAmount,
            'discount_percent' => $discountPercentage,
            'discount_amount' => $discountAmount,
            'final' => $finalAmount,
        ]);

        return [
            'original_amount' => $baseAmount,
            'discount_amount' => $discountAmount,
            'final_amount' => $finalAmount,
            'discount_percentage' => $discountPercentage,
        ];
    }

    /**
     * ===========================================================================
     * 4️⃣  COMMISSION BOUTIQUE PERSONNELLE
     * ===========================================================================
     * ✓ % appliqué sur le montant TOTAL de la commande utilisant son lien
     * ✓ L'acheteur voit le prix normal et paie le prix normal
     * ✓ La commission est créditée en arrière-plan au membre
     */
    public function creditPersonalShopCommission(Order $order, User $shopOwner = null)
    {
        if (!$shopOwner || !$order->user_id) {
            return null;
        }

        return DB::transaction(function () use ($order, $shopOwner) {
            $shopCommissionPercentage = floatval(Setting::get('shop_commission_percentage', 15));

            if ($shopCommissionPercentage <= 0) {
                return null;
            }

            // Appliquer le % sur le montant TOTAL
            $commissionAmount = ($order->total_amount * $shopCommissionPercentage) / 100;

            if ($commissionAmount <= 0) {
                return null;
            }

            // Créditer le wallet du propriétaire de la boutique
            $this->walletService->credit(
                $shopOwner,
                $commissionAmount,
                'shop_commission',
                "Commission boutique personnelle - Commande #{$order->order_number}",
                [
                    'order_id' => $order->id,
                    'buyer_id' => $order->user_id,
                    'shop_owner_id' => $shopOwner->id,
                ]
            );

            // Tracer dans le suivi mensuel
            $monthlyTracking = MonthlySalesTracking::getCurrentMonth($shopOwner->id);
            $monthlyTracking->increment('personal_shop_commission', $commissionAmount);

            Log::info('✅ Commission boutique créditée', [
                'shop_owner_id' => $shopOwner->id,
                'order_id' => $order->id,
                'order_amount' => $order->total_amount,
                'commission_percent' => $shopCommissionPercentage,
                'commission_amount' => $commissionAmount,
            ]);

            return [
                'commission_amount' => $commissionAmount,
                'percentage' => $shopCommissionPercentage,
                'order_amount' => $order->total_amount,
            ];
        });
    }

    /**
     * ===========================================================================
     * 5️⃣  COMMISSIONS MLM (Niveau 1 et 2)
     * ===========================================================================
     * ✓ Parrain DIRECT (niveau 1) reçoit % sur achat du filleul
     * ✓ Parrain INDIRECT (niveau 2) reçoit % sur achat du filleul de son filleul
     * ✓ Conditions: subscription_paid + is_active + AMM atteint ce mois
     * ✓ Pour produits d'investissement: commissions dès paiement confirmé
     * ✓ Pour produits physiques: commissions à la livraison
     */
    public function calculateAndCreditMLMCommissions(Order $order): array
    {
        $user = $order->user;

        if (!$user || !$user->sponsor_id) {
            Log::info('MLM : pas de parrain pour cet achat', [
                'order_id' => $order->id, 
                'order_number' => $order->order_number,
                'user_id' => $user->id ?? null
            ]);
            return [];
        }

        // VÉRIFICATION: Feature toggle pour les commissions MLM
        if (!FeatureToggle::isEnabled('mlm_commissions')) {
            Log::info('MLM : commissions désactivées par feature toggle', [
                'order_id' => $order->id
            ]);
            return [];
        }

        // Pour achats mensuels AMM et abonnements: commissions dès paiement confirmé
        // Pour produits physiques réguliers: commissions dès paiement aussi (MODIFIÉ - était à la livraison)
        // LOGIQUE CORRIGÉE: Créer les commissions dès que le paiement est confirmé (paid)
        // Cela permet aux sponsors de gagner immédiatement, même si la livraison prend du temps
        $canProcessCommission = ($order->payment_status === 'paid');

        if (!$canProcessCommission) {
            Log::info('MLM : commande pas encore éligible aux commissions', [
                'order_id' => $order->id,
                'order_type' => $order->order_type,
                'payment_status' => $order->payment_status,
                'status' => $order->status,
                'reason' => 'Paiement non confirmé (payment_status != paid)'
            ]);
            return [];
        }

        return DB::transaction(function () use ($order, $user) {
            $commissionsCreated = [];
            $currentSponsor = User::find($user->sponsor_id);
            $level = 1;
            $maxLevels = 2;

            Log::info("🎯 Calcul commissions MLM pour achat", [
                'order_id' => $order->id,
                'order_number' => $order->order_number,
                'buyer_id' => $user->id,
                'buyer_name' => $user->name,
                'order_amount' => $order->total_amount,
                'parrain_direct_id' => $currentSponsor->id ?? null,
            ]);

            while ($currentSponsor && $level <= $maxLevels) {
                $commissionRate = $this->getCommissionRateForLevel($level);
                $levelLabel = $level === 1 ? 'DIRECT (Niveau 1)' : 'INDIRECT (Niveau 2)';

                Log::info("🔍 Vérification parrain {$levelLabel}", [
                    'sponsor_id' => $currentSponsor->id,
                    'sponsor_name' => $currentSponsor->name,
                    'commission_rate' => $commissionRate . '%',
                ]);

                // Vérification 1: Abonnement payé
                if (!$currentSponsor->subscription_paid) {
                    Log::warning("❌ Parrain {$levelLabel} inéligible : abonnement non payé", [
                        'sponsor_id' => $currentSponsor->id,
                        'sponsor_name' => $currentSponsor->name,
                    ]);
                    $currentSponsor = $currentSponsor->sponsor_id ? User::find($currentSponsor->sponsor_id) : null;
                    $level++;
                    continue;
                }

                // Vérification 2: Compte actif
                if (!$currentSponsor->is_active) {
                    Log::warning("❌ Parrain {$levelLabel} inéligible : compte inactif", [
                        'sponsor_id' => $currentSponsor->id,
                        'sponsor_name' => $currentSponsor->name,
                    ]);
                    $currentSponsor = $currentSponsor->sponsor_id ? User::find($currentSponsor->sponsor_id) : null;
                    $level++;
                    continue;
                }

                // Vérification 3: AMM atteint ce mois-ci (OBLIGATOIRE)
                // Le sponsor doit avoir atteint son Achat Minimum Mensuel pour recevoir des commissions
                $sponsorMonthlyTracking = MonthlySalesTracking::getCurrentMonth($currentSponsor->id);
                $ammRequired = floatval(Setting::get('minimum_monthly_purchase', 50000));

                if ($sponsorMonthlyTracking->total_purchase_amount < $ammRequired) {
                    Log::warning("❌ Parrain {$levelLabel} inéligible : AMM non atteint ce mois", [
                        'sponsor_id' => $currentSponsor->id,
                        'sponsor_name' => $currentSponsor->name,
                        'current_amm' => $sponsorMonthlyTracking->total_purchase_amount,
                        'required_amm' => $ammRequired,
                        'deficit' => $ammRequired - $sponsorMonthlyTracking->total_purchase_amount,
                    ]);
                    $currentSponsor = $currentSponsor->sponsor_id ? User::find($currentSponsor->sponsor_id) : null;
                    $level++;
                    continue;
                }

                // ✅ Toutes conditions remplies - Attribution de la commission
                if ($commissionRate > 0) {
                    $commissionAmount = ($order->total_amount * $commissionRate) / 100;

                    $commission = Commission::create([
                        'user_id' => $currentSponsor->id,
                        'order_id' => $order->id,
                        'from_user_id' => $user->id,
                        'type' => $level === 1 ? 'level1' : 'level2',
                        'level' => $level,
                        'amount' => $commissionAmount,
                        'status' => 'paid',
                        'description' => "Commission {$levelLabel} ({$commissionRate}%) - Achat de {$user->name} - Commande #{$order->order_number}",
                    ]);

                    $this->walletService->credit(
                        $currentSponsor,
                        $commissionAmount,
                        'commission',
                        "Commission {$levelLabel} ({$commissionRate}%) - Commande #{$order->order_number}",
                        [
                            'commission_id' => $commission->id, 
                            'order_id' => $order->id,
                            'buyer_id' => $user->id,
                            'level' => $level
                        ]
                    );

                    $commissionsCreated[] = $commission;

                    Log::info("✅ Commission {$levelLabel} créditée avec succès", [
                        'commission_id' => $commission->id,
                        'sponsor_id' => $currentSponsor->id,
                        'sponsor_name' => $currentSponsor->name,
                        'buyer_name' => $user->name,
                        'order_number' => $order->order_number,
                        'order_amount' => $order->total_amount,
                        'commission_rate' => $commissionRate . '%',
                        'commission_amount' => $commissionAmount . ' XOF',
                        'level' => $level,
                    ]);
                }

                // Passer au parrain suivant
                $currentSponsor = $currentSponsor->sponsor_id ? User::find($currentSponsor->sponsor_id) : null;
                $level++;
            }

            if (count($commissionsCreated) > 0) {
                Log::info("🎉 Total commissions MLM attribuées", [
                    'order_id' => $order->id,
                    'order_number' => $order->order_number,
                    'total_commissions' => count($commissionsCreated),
                    'total_amount' => array_sum(array_column($commissionsCreated, 'amount')) . ' XOF',
                ]);
            } else {
                Log::info("⚠️ Aucune commission MLM attribuée pour cet achat", [
                    'order_id' => $order->id,
                    'order_number' => $order->order_number,
                    'raison' => 'Aucun parrain éligible (vérifier subscription_paid + is_active + AMM)',
                ]);
            }

            return $commissionsCreated;
        });
    }

    /**
     * ===========================================================================
     * 6️⃣  FRAIS DE RETRAIT
     * ===========================================================================
     * ✓ % appliqué quand le membre demande un retrait
     * ✓ Validé avec montant minimum de retrait
     */
    public function calculateWithdrawalFee($amount): array
    {
        $withdrawalFeePercentage = floatval(Setting::get('withdrawal_fee_percentage', 3));
        $minWithdrawal = floatval(Setting::get('min_withdrawal_amount', 5000));

        if ($amount < $minWithdrawal) {
            return [
                'valid' => false,
                'reason' => "Montant minimum de retrait : {$minWithdrawal} XOF",
            ];
        }

        $fee = ($amount * $withdrawalFeePercentage) / 100;
        $netAmount = $amount - $fee;

        Log::info('✅ Frais de retrait calculés', [
            'gross_amount' => $amount,
            'fee_percent' => $withdrawalFeePercentage,
            'fee_amount' => $fee,
            'net_amount' => $netAmount,
        ]);

        return [
            'valid' => true,
            'gross_amount' => $amount,
            'fee_amount' => $fee,
            'fee_percentage' => $withdrawalFeePercentage,
            'net_amount' => $netAmount,
            'min_withdrawal' => $minWithdrawal,
        ];
    }

    /**
     * ===========================================================================
     * 7️⃣  DÉLAI Z - CONFIRMATION LIVRAISON
     * ===========================================================================
     * ✓ Délai avant que les réclamations ne soient plus acceptées
     */
    public function canClaimOrder(Order $order): bool
    {
        $delayDays = intval(Setting::get('delivery_confirmation_delay', 7));
        $deliveryDate = $order->delivered_at ?? $order->updated_at;

        $daysSinceDelivery = now()->diffInDays($deliveryDate);

        if ($daysSinceDelivery > $delayDays) {
            Log::info('❌ Délai de réclamation dépassé', [
                'order_id' => $order->id,
                'days_since_delivery' => $daysSinceDelivery,
                'allowed_days' => $delayDays,
            ]);
            return false;
        }

        return true;
    }

    /**
     * ===========================================================================
     * 8️⃣  POOL DE PARTAGE
     * ===========================================================================
     * ✓ Seuil d'activation : montant total d'AMM du réseau (tous les membres)
     * ✓ % prélevé et distribué équitablement
     */
    public function checkPoolActivation($month = null, $year = null): array
    {
        $month = $month ?? now()->month;
        $year = $year ?? now()->year;

        $poolThreshold = floatval(Setting::get('pool_share_threshold', 10000000));
        $poolPercentage = floatval(Setting::get('pool_share_percentage', 2));

        // Calculer la somme TOTALE des AMM atteints dans le réseau ce mois
        $networkAMM = MonthlySalesTracking::where('year', $year)
            ->where('month', $month)
            ->where('has_met_amm', true)
            ->sum('total_purchase_amount');

        $poolActivated = $networkAMM >= $poolThreshold;

        Log::info('📊 Vérification activation pool', [
            'month' => $month,
            'year' => $year,
            'network_amm' => $networkAMM,
            'threshold' => $poolThreshold,
            'activated' => $poolActivated,
        ]);

        return [
            'activated' => $poolActivated,
            'network_amm' => $networkAMM,
            'threshold' => $poolThreshold,
            'percentage' => $poolPercentage,
            'pool_amount' => $poolActivated ? ($networkAMM * $poolPercentage) / 100 : 0,
        ];
    }

    /**
     * ===========================================================================
     * UTILITAIRES INTERNES
     * ===========================================================================
     */

    protected function getCommissionRateForLevel($level): float
    {
        $rates = [
            1 => floatval(Setting::get('level_1_commission', 10)),
            2 => floatval(Setting::get('level_2_commission', 5)),
        ];

        return $rates[$level] ?? 0;
    }

    protected function canReceiveCommissions(User $user): bool
    {
        // Pour recevoir le BONUS DÉMARRAGE: juste subscription_paid suffit
        // Pour recevoir COMMISSIONS MLM: is_active + subscription_paid + AMM
        if (!$user->subscription_paid) {
            Log::debug('❌ Abonnement non payé', ['user_id' => $user->id]);
            return false;
        }

        // On retourne true pour le bonus démarrage même si inactif
        // La vérification is_active sera faite dans calculateAndCreditMLMCommissions()
        return true;
    }

    /**
     * Reset mensuel : appelé une fois par mois
     */
    public function resetMonthlyTracking($previousMonth = null, $previousYear = null)
    {
        $previousMonth = $previousMonth ?? now()->subMonth()->month;
        $previousYear = $previousYear ?? now()->subMonth()->year;

        Log::info('🔄 Reset mensuel du suivi des ventes', [
            'month' => $previousMonth,
            'year' => $previousYear,
        ]);

        // Les anciennes données restent pour historique, les nouvelles commencent à 0
        // Voir MonthlySalesTracking::getCurrentMonth()
    }
}
