<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laracasts\Presenter\PresentableTrait;

class User extends Authenticatable
{
    use HasFactory, Notifiable, PresentableTrait;

    protected $presenter = 'App\\Presenters\\UserPresenter';

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    protected $primaryKey = 'id';

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    protected $fillable = ['name', 'email', 'password'];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * Static cache for user counts to prevent repeated queries
     */
    protected static $countCache = [];

    /**
     * Get the e-mail address where password reminders are sent.
     *
     * @return string
     */
    public function getReminderEmail()
    {
        return $this->email;
    }

    /**
     * User posts
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function posts()
    {
        return $this->hasMany('App\\Models\\Post', 'user_id');
    }

    /**
     * User Group
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function group()
    {
        return $this->belongsTo('Addon\\User\\Model\\Group', 'user_group');
    }

    /**
     * OPTIMIZED: Get friends with caching
     */
    public function friends($limit = 10)
    {
        $cacheKey = "user_friends_{$this->id}_{$limit}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            static::$countCache[$cacheKey] = app('App\\Repositories\\ConnectionRepository')->getFriends($this->id, $limit);
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Count friends with caching and direct query
     */
    public function countFriends($cmId = 0)
    {
        $cacheKey = "count_friends_{$this->id}_{$cmId}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Use direct database query instead of repository for better performance
            $count = \DB::table('connections')
                ->where(function ($query) {
                    $query->where('user_id', $this->id)
                          ->orWhere('connection_id', $this->id);
                })
                ->where('status', 1) // Assuming 1 means accepted friendship
                ->count();
                
            static::$countCache[$cacheKey] = $count;
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Get followers with caching
     */
    public function followers($limit = 10)
    {
        $cacheKey = "user_followers_{$this->id}_{$limit}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            static::$countCache[$cacheKey] = app('App\\Repositories\\ConnectionRepository')->followers($this->id, $limit);
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Count followers with direct query
     */
    public function countFollowers()
    {
        $cacheKey = "count_followers_{$this->id}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Direct query for better performance
            $count = \DB::table('connections')
                ->where('connection_id', $this->id)
                ->where('status', 2) // Assuming 2 means following
                ->count();
                
            static::$countCache[$cacheKey] = $count;
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Count following with direct query
     */
    public function countFollowing()
    {
        $cacheKey = "count_following_{$this->id}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Direct query for better performance
            $count = \DB::table('connections')
                ->where('user_id', $this->id)
                ->where('status', 2) // Assuming 2 means following
                ->count();
                
            static::$countCache[$cacheKey] = $count;
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Get following with caching
     */
    public function following($limit = 10)
    {
        $cacheKey = "user_following_{$this->id}_{$limit}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            static::$countCache[$cacheKey] = app('App\\Repositories\\ConnectionRepository')->following($this->id, $limit);
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Count mutual friends with direct query
     */
    public function countMutual()
    {
        $cacheKey = "count_mutual_{$this->id}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Use direct query for better performance
            static::$countCache[$cacheKey] = app('App\\Repositories\\ConnectionRepository')->mutualFriendsCount($this->id);
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * Easy method to check if the login user is the owner of this user
     *
     * @return bool
     */
    public function isOwner()
    {
        return \Auth::check() and \Auth::user()->id == $this->id;
    }

    public function isAdmin()
    {
        return $this->admin;
    }

    /**
     * OPTIMIZED: Update online status with throttling to prevent excessive database writes
     */
    public function updateOnline()
    {
        // Throttle updates - only update if last update was more than 60 seconds ago
        $cacheKey = "last_online_update_{$this->id}";
        $lastUpdate = \Cache::get($cacheKey, 0);
        $now = time();
        
        if ($now - $lastUpdate < 60) {
            return; // Skip update if too recent
        }
        
        \Cache::put($cacheKey, $now, 300); // Cache for 5 minutes
        
        $this->last_active_time = $now;
        if ($this->online_status == 0 or $this->online_status != 2) {
            $privacy = $this->present()->privacy('self-offline', 0);
            if ($privacy == 0) {
                $this->online_status = 1;
            }
        }
        $this->save();
    }

    /**
     * OPTIMIZED: Update status with caching
     */
    public function updateStatus($s, $self = false)
    {
        if (! \Auth::user()) {
            return false;
        }
        
        $this->online_status = $s;
        $repository = app('App\\Repositories\\UserRepository');
        
        if ($self and $s == 0) {
            $repository->savePrivacy(['self-offline' => 1]);
        } else {
            if ($s == 0) {
                $repository->savePrivacy(['self-offline' => 0]);
            }
        }
        
        $this->save();
        
        // Clear related caches
        $this->clearUserCache();
    }

    /**
     * Photos relationship
     */
    public function photos()
    {
        return $this->hasMany('App\\Models\\Photos', 'user_id')->where('slug', 'LIKE', '%album-%');
    }

    /**
     * CRITICAL FIX: Use database count instead of loading all records
     */
    public function countPhotos()
    {
        $cacheKey = "count_photos_{$this->id}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Use database count instead of loading all records
            $photos = $this->photos()->count();
            $video = app('App\\Repositories\\VideoRepository')->count($this->id);
            
            static::$countCache[$cacheKey] = $photos + $video;
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * CRITICAL FIX: Use database count instead of loading all posts
     */
    public function countPosts()
    {
        $cacheKey = "count_posts_{$this->id}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            // Use database count instead of count($this->posts)
            static::$countCache[$cacheKey] = $this->posts()->count();
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * OPTIMIZED: Get user photos with limit to prevent loading all
     */
    public function usersPhotos($limit = 50)
    {
        $cacheKey = "user_photos_{$this->id}_{$limit}";
        
        if (!isset(static::$countCache[$cacheKey])) {
            static::$countCache[$cacheKey] = $this->hasMany('App\\Models\\Photos', 'user_id')
                ->where('slug', 'LIKE', '%album-%')
                ->limit($limit)
                ->get();
        }
        
        return static::$countCache[$cacheKey];
    }

    /**
     * Clear user-specific cache
     */
    public function clearUserCache()
    {
        $keysToRemove = [];
        foreach (static::$countCache as $key => $value) {
            if (strpos($key, "_{$this->id}") !== false) {
                $keysToRemove[] = $key;
            }
        }
        
        foreach ($keysToRemove as $key) {
            unset(static::$countCache[$key]);
        }
        
        // Also clear Laravel cache for this user
        $cacheKeys = [
            "last_online_update_{$this->id}",
            "user_permissions_{$this->id}",
            "user_roles_{$this->id}"
        ];
        
        foreach ($cacheKeys as $key) {
            \Cache::forget($key);
        }
    }
}
