<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'email_verified_at',
        'role',
        'balance',
        'deposited',
        'available_deposit',
        'total_earned',
        'today_earned',
        'activity_points',
        'ip_address',
        'last_login_ip',
        'last_activity_ip',
        'activity_count',
        'suspected',
        'banned',
        'country',
        'last_active',
        'referred_by',
        'referral_count',
        'gauth_id',
        'gauth_type',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_secret',
    ];

    /**
     * The attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'balance' => 'decimal:6',
        'deposited' => 'decimal:6',
        'available_deposit' => 'decimal:6',
        'total_earned' => 'decimal:6',
        'today_earned' => 'decimal:6',
        'last_active' => 'integer',
        'referred_by' => 'integer',
    ];
    public static function updateLastActivity($userId = null, $ip = null) 
    {
        $userId = $userId ?? Auth::id();
    
        if (!$userId) {
            return false;
        }
    
        self::where('id', $userId)->update([
            'last_active' => now()->timestamp,
            'last_activity_ip' => $ip ?? request()->ip(),
        ]);
        
        $user = self::where('id', $userId)->first();
    
        if ($user->activity_count == (get_setting('min_activity_count')-1)) {
            if (!empty($user->referred_by) && $user->referred_by != 0) {
                self::where('id', $user->referred_by)
                    ->increment('referral_count');
            }
        }
        
        self::where('id', $userId)->increment('activity_count');

        $expiresAt = now()->addMinutes(10);
        $onlineUsers = Cache::get('online-users', []);
    
        $onlineUsers[$userId] = now()->timestamp;
    
        Cache::put('online-users', $onlineUsers, $expiresAt);
    
        $count = count(array_filter($onlineUsers, function ($lastActive) {
            return $lastActive >= now()->timestamp - (10 * 60);
        }));
        Cache::put('online-users-count', $count, $expiresAt);
    
        return true;
    }
    
    public static function getOnlineUsersCount()
    {
        return Cache::get('online-users-count', function () {
            $onlineUsers = Cache::get('online-users', []);
            $now = now()->timestamp;
    
            $filteredUsers = array_filter($onlineUsers, function ($lastActive) use ($now) {
                return $lastActive >= ($now - (10 * 60));
            });
    
            Cache::put('online-users-count', count($filteredUsers), now()->addMinutes(5));
    
            return count($filteredUsers);
        });
    }

    public function earn($amount, $is_referral = false)
    {
        $this->increment('balance', $amount);
        $this->increment('total_earned', $amount);
        $this->increment('today_earned', $amount);
        if(!$is_referral) {
            $this->increment('activity_points', $amount*1000000);
        }
    }
    public function reduce($amount)
    {
        $this->decrement('balance', $amount);
        $this->decrement('total_earned', $amount);
        $this->decrement('today_earned', $amount);
    }
    public function detectAndMarkMultiAccount($userId = null, $ip = null)
    {
        $userId = $userId ?? Auth::id();
    
        if (!$userId) {
            return false;
        }
    
        $currentUser = self::find($userId);
        if (!$currentUser) {
            return false;
        }
    
        $currentIp = $ip ?? $currentUser->last_activity_ip;
    
        $users = self::where('id', '!=', $userId)
            ->where(function ($q) use ($currentIp) {
                $q->where('ip_address', $currentIp)
                  ->orWhere('last_login_ip', $currentIp)
                  ->orWhere('last_activity_ip', $currentIp);
            })
            ->get();
            
        if ($users->isNotEmpty()) {
            $targetUsers = self::whereIn('id', $users->pluck('id'))
                ->whereNotIn('role', ['Admin', 'Superadmin']);
        
            self::where('id', $userId)
                ->whereNotIn('role', ['Admin', 'Superadmin'])
                ->update(['suspected' => 1]);
        
            $targetUsers->update(['suspected' => 1]);
        
            if (get_setting('auto_banned') === 'on') {
                self::where('id', $userId)
                    ->whereNotIn('role', ['Admin', 'Superadmin'])
                    ->update(['banned' => 1]);
        
                $targetUsers->update(['banned' => 1]);
            }
        
            return true;
        }

    
        return false;
    }
    public function withdrawHistory()
    {
        return $this->hasMany(WithdrawHistory::class, 'user_id');
    }
    
    public function referrals()
    {
        return $this->hasMany(User::class, 'referred_by');
    }
}
