<?php

/**
 * =====================================================
 * DOCUMENTATION: LOGIQUE DE CALCUL COMMISSIONS MLM
 * =====================================================
 * 
 * STRUCTURE COMMISSIONS:
 * 1. Commission de vente directe (SALE)
 * 2. Commissions niveaux (LEVEL 1-7)
 * 3. Bonus volumes (VOLUME_BONUS)
 * 4. Bonus rapide (QUICK_START)
 * 5. Bonus paliers (RANK_BONUS)
 * 
 * FLUX DE TRAITEMENT:
 * 1. Client effectue achat → Créer Order
 * 2. Paiement approuvé → Créer WalletTransaction (type: purchase)
 * 3. Commission trigger → Calculer selon règles
 * 4. Créer Commission records
 * 5. Créditer portefeuilles
 */

namespace App\Services;

use App\Models\Commission;
use App\Models\User;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\MlmLevel;
use App\Models\WalletTransaction;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;

class MLMCommissionService
{
    /**
     * Calculer et créditer commissions pour une commande
     * 
     * @param Order $order
     * @throws \Exception
     */
    public static function processOrderCommissions(Order $order)
    {
        DB::beginTransaction();
        try {
            $seller = $order->seller;
            $buyer = $order->user;

            // 1. Commission de vente directe (10% par défaut)
            self::createDirectSaleCommission($order, $seller);

            // 2. Commissions MLM pour le sponsor et chaîne
            if ($buyer->role === 'member' && $buyer->sponsor_id) {
                self::createMLMChainCommissions($order, $buyer);
            }

            // 3. Bonus volumes
            self::createVolumeBonusCommissions($order, $seller, $buyer);

            // 4. Bonus rapide (first purchase)
            if (!$buyer->first_purchase_done) {
                self::createQuickStartBonus($buyer, $order);
            }

            DB::commit();
            Log::info("Commissions traitées pour commande #{$order->id}");

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error("Erreur traitement commissions: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Commission vente directe (seller)
     * 
     * Calcul: (Montant commande - Frais) * Taux seller
     * Taux défaut: 10% de la vente brute
     */
    private static function createDirectSaleCommission(Order $order, $seller)
    {
        $saleAmount = $order->total_amount;
        $commissionRate = $seller->commission_rate ?? 10; // Défaut 10%
        $commissionAmount = ($saleAmount * $commissionRate) / 100;

        Commission::create([
            'user_id' => $seller->user_id,
            'order_id' => $order->id,
            'from_user_id' => null,
            'type' => 'sale',
            'level' => 0,
            'amount' => $commissionAmount,
            'status' => 'pending',
            'description' => "Vente directe - Commande #{$order->id}"
        ]);
    }

    /**
     * Commissions MLM chaîne sponsorship
     * 
     * Structure par défaut (modifiable via MlmLevel):
     * - Niveau 1 (Sponsor direct): 5%
     * - Niveau 2: 3%
     * - Niveau 3: 2%
     * - Niveau 4: 1%
     * - Niveau 5+: 0.5%
     * 
     * NOTE: Achats additionnels (non-first-purchase) ne triggent PAS commissions MLM
     *       Seul le premier achat de chaque utilisateur trigger les commissions
     */
    private static function createMLMChainCommissions(Order $order, User $buyer)
    {
        // Vérifier si c'est le premier achat
        if ($buyer->first_purchase_done) {
            Log::info("Achat récurrent - Pas de commissions MLM pour achat #{$order->id}");
            return;
        }

        $saleAmount = $order->total_amount;
        $currentUser = $buyer;
        $level = 1;

        // Remonter la chaîne jusqu'à 7 niveaux
        while ($currentUser->sponsor_id && $level <= 7) {
            $sponsor = User::find($currentUser->sponsor_id);
            if (!$sponsor) break;

            // Obtenir taux du niveau
            $mlmLevel = MlmLevel::where('level', $level)->first();
            if (!$mlmLevel) {
                Log::warning("Niveau MLM {$level} non configuré");
                break;
            }

            $commissionRate = $mlmLevel->commission_rate;
            $commissionAmount = ($saleAmount * $commissionRate) / 100;

            // Créer commission
            Commission::create([
                'user_id' => $sponsor->id,
                'order_id' => $order->id,
                'from_user_id' => $currentUser->id,
                'type' => "level{$level}",
                'level' => $level,
                'amount' => $commissionAmount,
                'status' => 'pending',
                'description' => "Commission niveau {$level} - Achat de {$buyer->name}"
            ]);

            $currentUser = $sponsor;
            $level++;
        }
    }

    /**
     * Bonus volumes (basé volume équipe)
     * 
     * À implémenter selon logique métier:
     * Ex: Si volume équipe > 100k XOF → +2% bonus
     */
    private static function createVolumeBonusCommissions(Order $order, $seller, $buyer)
    {
        // TODO: Implémenter selon règles business
        // Exemple simple:
        // $teamVolume = $buyer->getTeamVolume();
        // if ($teamVolume > 100000 && $buyer->role === 'member') {
        //     $bonus = ($order->total_amount * 2) / 100;
        //     Commission::create([...])
        // }
    }

    /**
     * Bonus premier achat
     * 
     * Récompense le premier acheteur: montant configuré dans Settings
     */
    private static function createQuickStartBonus(User $buyer, Order $order)
    {
        // Récupérer le montant du bonus depuis les Settings
        $bonusAmount = floatval(\App\Models\Setting::get('first_purchase_bonus', 1000));
        
        if ($bonusAmount <= 0) {
            Log::info("Bonus premier achat désactivé (montant = 0)");
            return;
        }
        
        Commission::create([
            'user_id' => $buyer->id,
            'order_id' => $order->id,
            'from_user_id' => null,
            'type' => 'quick_start',
            'amount' => $bonusAmount,
            'status' => 'pending',
            'description' => 'Bonus premier achat'
        ]);
        
        Log::info("Bonus premier achat créé: {$bonusAmount} XOF pour user #{$buyer->id}");
    }

    /**
     * Créditer commission dans le portefeuille
     * 
     * Appel par: système batch (via scheduler) ou webhook
     */
    public static function creditCommission(Commission $commission)
    {
        DB::beginTransaction();
        try {
            // Vérifier si pas encore payée
            if ($commission->status !== 'pending') {
                return;
            }

            $user = $commission->user;
            
            // S'assurer que le wallet existe
            $wallet = $user->wallet;
            if (!$wallet) {
                $wallet = \App\Models\Wallet::firstOrCreate(
                    ['user_id' => $user->id],
                    [
                        'balance' => 0,
                        'status' => 'active',
                        'currency' => 'XOF',
                    ]
                );
            }

            // Créditer le portefeuille
            $wallet->increment('balance', $commission->amount);
            $wallet->increment('total_earned', $commission->amount);

            // Créer transaction
            WalletTransaction::create([
                'wallet_id' => $wallet->id,
                'user_id' => $user->id,
                'type' => 'commission',
                'amount' => $commission->amount,
                'balance_before' => $wallet->balance - $commission->amount,
                'balance_after' => $wallet->balance,
                'status' => 'completed',
                'reference' => 'COMM-' . $commission->id,
                'description' => $commission->description,
                'related_commission_id' => $commission->id,
            ]);

            // Marquer commission comme payée
            $commission->update(['status' => 'paid']);

            DB::commit();
            Log::info("Commission #{$commission->id} payée à {$user->name}");

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error("Erreur crédit commission: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Valider arbre généalogique (pas de boucles)
     * 
     * @param User $user
     * @return bool
     */
    public static function validateSponsorshipTree(User $user)
    {
        $visited = [];
        $current = $user;
        $maxDepth = 1000; // Limite de sécurité
        $depth = 0;

        while ($current->sponsor_id && $depth < $maxDepth) {
            if (in_array($current->sponsor_id, $visited)) {
                Log::error("Boucle détectée dans arbre MLM pour user {$user->id}");
                return false;
            }

            $visited[] = $current->sponsor_id;
            $current = User::find($current->sponsor_id);
            
            if (!$current) break;
            $depth++;
        }

        return true;
    }
}
