<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Helpers\RoleHelper;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'first_name',
        'last_name',
        'username',
        'email',
        'password',
        'member_code',
        'referral_code',
        'sponsor_code',
        'phone',
        'country',
        'country_code',
        'city',
        'address',
        'whatsapp',
        'sponsor_id',
        'role',
        'rank_id',
        'preferred_language',
        'preferred_currency',
        'is_active',
        'is_banned',
        'ban_reason',
        'subscription_paid',
        'first_purchase_done',
        'last_purchase_date',
        'total_commissions',
        'discount_percentage',
        'email_verified_at',
        'email_verification_code',
        'verification_code_sent_at',
        'two_factor_enabled',
        'two_factor_secret',
        'kyc_status',
        'kyc_documents',
        'total_loyalty_points',
        'downline_count',
        'profile_photo',
        'bio',
        'privacy_policy',
        'admin_created',
        'impersonated_by',
        'original_user_id',
        'has_paid_investment_product',
        'investment_product_paid_at',
        'amm_exemption_until',
        'amm_advance_paid_until',
        'subscription_paid_at',
    ];

    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_secret',
    ];

    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'is_active' => 'boolean',
            'is_banned' => 'boolean',
            'subscription_paid' => 'boolean',
            'first_purchase_done' => 'boolean',
            'last_purchase_date' => 'datetime',
            'verification_code_sent_at' => 'datetime',
            'total_commissions' => 'decimal:2',
            'available_balance' => 'decimal:2',
            'discount_percentage' => 'decimal:2',
            'two_factor_enabled' => 'boolean',
            'kyc_documents' => 'array',
            'has_paid_investment_product' => 'boolean',
            'investment_product_paid_at' => 'datetime',
            'amm_exemption_until' => 'date',
            'amm_advance_paid_until' => 'date',
            'subscription_paid_at' => 'datetime',
        ];
    }

    public function addresses()
    {
        return $this->hasMany(UserAddress::class);
    }

    public function sponsor()
    {
        return $this->belongsTo(User::class, 'sponsor_id');
    }

    public function referrals()
    {
        return $this->hasMany(User::class, 'sponsor_id');
    }
    
    public function downline()
    {
        return $this->hasMany(User::class, 'sponsor_id');
    }

    /**
     * Filleuls directs - utilise la relation sponsor_id dans users
     * (et non la table referrals qui peut être vide)
     */
    public function directReferrals()
    {
        return $this->hasMany(User::class, 'sponsor_id');
    }

    /**
     * Tous les filleuls (via table referrals si peuplée, sinon via sponsor_id)
     */
    public function allReferrals()
    {
        // Fallback: si la table referrals est vide, utiliser sponsor_id
        if (Referral::where('sponsor_id', $this->id)->exists()) {
            return $this->hasMany(Referral::class, 'sponsor_id');
        }
        return $this->hasMany(User::class, 'sponsor_id');
    }

    public function commissions()
    {
        return $this->hasMany(Commission::class);
    }

    public function orders()
    {
        return $this->hasMany(Order::class);
    }

    public function activityLogs()
    {
        return $this->hasMany(UserActivityLog::class);
    }

    public function wallet()
    {
        return $this->hasOne(Wallet::class);
    }

    public function walletTransactions()
    {
        return $this->hasMany(WalletTransaction::class);
    }

    public function savingsLocks()
    {
        return $this->hasMany(SavingsLock::class);
    }

    public function withdrawals()
    {
        return $this->hasMany(Withdrawal::class);
    }

    public function seller()
    {
        return $this->hasOne(Seller::class);
    }

    public function rank()
    {
        return $this->belongsTo(Rank::class);
    }

    public function loyaltyPoints()
    {
        return $this->hasMany(LoyaltyPoint::class);
    }

    public function investments()
    {
        return $this->hasMany(UserInvestment::class);
    }

    public function investmentTransactions()
    {
        return $this->hasMany(InvestmentTransaction::class);
    }

    public function investmentInterests()
    {
        return $this->hasMany(InvestmentInterest::class);
    }

    public function documents()
    {
        return $this->hasMany(SellerDocument::class);
    }

    public function disputes()
    {
        return $this->hasMany(Dispute::class, 'initiator_id')
            ->orWhere('respondent_id', $this->id);
    }

    public function deliveries()
    {
        return $this->hasMany(Delivery::class, 'assigned_to');
    }

    public function auditLogs()
    {
        return $this->hasMany(AuditLog::class);
    }

    public function reviews()
    {
        return $this->hasMany(Review::class);
    }

    public function notifications()
    {
        return $this->hasMany(Notification::class);
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeMembers($query)
    {
        return $query->where('role', 'member');
    }

    public function scopeSellers($query)
    {
        return $query->where('role', 'seller');
    }

    public function scopeAffiliates($query)
    {
        return $query->where('role', 'affiliate');
    }

    public function getFullNameAttribute()
    {
        if ($this->first_name && $this->last_name) {
            return $this->first_name . ' ' . $this->last_name;
        }
        return $this->name;
    }

    public function getNetworkStatsAttribute()
    {
        $stats = ['total' => 0, 'levels' => []];
        
        for ($level = 1; $level <= 10; $level++) {
            $count = Referral::where('sponsor_id', $this->id)
                ->where('level', $level)
                ->count();
            $stats['levels'][$level] = $count;
            $stats['total'] += $count;
        }
        
        return $stats;
    }

    public function getTotalCommissionsEarnedAttribute()
    {
        return $this->commissions()->sum('amount');
    }

    public function getPendingCommissionsAttribute()
    {
        return $this->commissions()->where('status', 'pending')->sum('amount');
    }

    public function getPaidCommissionsAttribute()
    {
        return $this->commissions()->where('status', 'paid')->sum('amount');
    }

    public function getWalletBalanceAttribute()
    {
        return $this->wallet ? $this->wallet->balance : 0;
    }

    public function canReceiveCommissions()
    {
        return $this->is_active && 
               !$this->is_banned && 
               $this->subscription_paid &&
               $this->first_purchase_done;
    }

    public function isSeller()
    {
        return $this->role === 'seller' && $this->seller && $this->seller->canSell();
    }

    public function isAdmin()
    {
        // Super admin et administrateurs ont l'accès administratif
        return RoleHelper::isAdmin($this->role);
    }

    public function isBackOfficeStaff()
    {
        return RoleHelper::canAccessBackoffice($this->role);
    }

    public function hasFullAdminAccess()
    {
        return in_array($this->role, ['super_admin', 'admin']);
    }

    public function isAffiliate()
    {
        return RoleHelper::canSponsor($this->role);
    }

    public function isMember()
    {
        return RoleHelper::canAccessMemberArea($this->role);
    }

    public function getRoleName()
    {
        return RoleHelper::getLabel($this->role);
    }

    public function getRoleBadgeClass()
    {
        return RoleHelper::getBadgeClass($this->role);
    }

    public function canSponsor()
    {
        return RoleHelper::canSponsor($this->role);
    }

    /**
     * Obtenir la taille de l'équipe (tous les filleuls directs)
     * Utilise la relation sponsor_id dans users au lieu de la table referrals
     */
    public function getTeamSize()
    {
        return User::where('sponsor_id', $this->id)->count();
    }

    /**
     * Obtenir les ventes de l'équipe (filleuls directs)
     * Utilise la relation sponsor_id dans users au lieu de la table referrals
     */
    public function getTeamSales()
    {
        $teamIds = User::where('sponsor_id', $this->id)->pluck('id');
        
        return Order::whereIn('user_id', $teamIds)
            ->whereIn('status', ['completed', 'delivered'])
            ->sum('total_amount');
    }

    public function getUnreadNotificationsCount()
    {
        return $this->notifications()->where('is_read', false)->count();
    }

    /**
     * Obtenir le solde disponible du portefeuille
     * Source de vérité: wallets.balance
     * @return decimal
     */
    public function getBalance()
    {
        return $this->wallet->balance ?? 0;
    }

    /**
     * Obtenir le solde en attente
     * @return decimal
     */
    public function getPendingBalance()
    {
        return $this->wallet->pending_balance ?? 0;
    }

    public static function generateMemberCode($firstName, $lastName)
    {
        $baseCode = strtoupper(substr($firstName, 0, 1) . substr($lastName, 0, 2));
        $code = $baseCode . rand(100, 999);
        
        while (self::where('member_code', $code)->exists()) {
            $code = $baseCode . rand(100, 999);
        }
        
        return $code;
    }

    public static function generateReferralCode()
    {
        do {
            $code = strtoupper(\Illuminate\Support\Str::random(8));
        } while (self::where('referral_code', $code)->exists());

        return $code;
    }
}
