<?php

namespace App\Models;

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

use App\Models\Department;
use App\Models\Designation;
use App\Models\Shift;
use App\Models\Employee;
use App\Models\EmployeeSalaryStructure;
use App\Models\EmployeeSalaryHistory;
use App\Models\EmployeeAttendance;
use App\Models\Payroll;
use App\Models\PayrollItem;
use App\Models\EmployeeAdvance;
use App\Models\PayrollPayment;
use App\Models\EmployeeLedger;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /*
    |--------------------------------------------------------------------------
    | Mass Assignable
    |--------------------------------------------------------------------------
    */

    protected $fillable = [
        'uid',
        'name',
        'username',
        'phone',
        'email',
        'password',
        'photo',
        'status',
        'last_login_at',
        'last_logout_at',
        'last_activity_at',
    ];

    /*
    |--------------------------------------------------------------------------
    | Hidden Fields
    |--------------------------------------------------------------------------
    */

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

    /*
    |--------------------------------------------------------------------------
    | Casts
    |--------------------------------------------------------------------------
    */

    protected $casts = [
        'email_verified_at' => 'datetime',
        'password'          => 'hashed',
        'last_login_at'     => 'datetime',
        'last_logout_at'    => 'datetime',
        'last_activity_at'  => 'datetime',
    ];

    /*
    |--------------------------------------------------------------------------
    | Appended Attributes
    |--------------------------------------------------------------------------
    */

    protected $appends = [
        'is_online',
    ];

    /*
    |--------------------------------------------------------------------------
    | Boot Method (UID Generator)
    |--------------------------------------------------------------------------
    */

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($user) {

            if (!$user->uid) {
                $lastId = self::max('id') + 1;
                $user->uid = 'USR' . str_pad($lastId, 3, '0', STR_PAD_LEFT);
            }

        });
    }

    /*
    |--------------------------------------------------------------------------
    | Relationships
    |--------------------------------------------------------------------------
    */

    public function suppliers(): HasMany
    {
        return $this->hasMany(Supplier::class);
    }

    public function customers(): HasMany
    {
        return $this->hasMany(Customer::class);
    }

    public function subscriptions(): HasMany
    {
        return $this->hasMany(Subscription::class);
    }

    public function expenses(): HasMany
    {
        return $this->hasMany(Expense::class);
    }

    public function accounts(): HasMany
    {
        return $this->hasMany(UserAccount::class);
    }

    public function expenseCategories(): HasMany
    {
        return $this->hasMany(ExpenseCategory::class);
    }

    public function customerTransactions(): HasMany
    {
        return $this->hasMany(CustomerTransaction::class);
    }

    public function supplierTransactions(): HasMany
    {
        return $this->hasMany(SupplierTransaction::class);
    }

    public function departments()
    {
        return $this->hasMany(Department::class);
    }

    public function designations()
    {
        return $this->hasMany(Designation::class);
    }

    public function shifts()
    {
        return $this->hasMany(Shift::class);
    }

    public function employees()
    {
        return $this->hasMany(Employee::class);
    }

    public function employeeSalaryStructures()
    {
        return $this->hasMany(EmployeeSalaryStructure::class);
    }

    public function employeeSalaryHistories()
    {
        return $this->hasMany(EmployeeSalaryHistory::class);
    }

    public function employeeAttendances()
    {
        return $this->hasMany(EmployeeAttendance::class);
    }

    public function payrolls()
    {
        return $this->hasMany(Payroll::class);
    }

    public function payrollItems()
    {
        return $this->hasMany(PayrollItem::class);
    }

    public function employeeAdvances()
    {
        return $this->hasMany(EmployeeAdvance::class);
    }

    public function payrollPayments()
    {
        return $this->hasMany(PayrollPayment::class);
    }

    public function employeeLedgers()
    {
        return $this->hasMany(EmployeeLedger::class);
    }

    /*
    |--------------------------------------------------------------------------
    | Online / Offline System
    |--------------------------------------------------------------------------
    */

    public function getIsOnlineAttribute(): bool
    {
        if (Cache::has($this->onlineCacheKey())) {
            return true;
        }

        if (!$this->last_activity_at) {
            return false;
        }

        return $this->last_activity_at->greaterThanOrEqualTo(
            now()->subMinutes(config('presence.online_window_minutes', 2))
        );
    }

    public function onlineCacheKey(): string
    {
        return 'user-online-' . $this->id;
    }

    /*
    |--------------------------------------------------------------------------
    | Helper Methods
    |--------------------------------------------------------------------------
    */

    public function activeSubscription(): ?Subscription
    {
        return $this->subscriptions()
            ->where('status', 'active')
            ->where('end_date', '>=', now())
            ->latest('end_date')
            ->first();
    }

    public function totalBalance(): float
    {
        return (float) $this->accounts()->sum('balance');
    }

    public function isBlocked(): bool
    {
        return $this->status === 'blocked';
    }

    public function profilePhoto(): string
    {
        return $this->photo
            ? asset('storage/' . $this->photo)
            : asset('images/default-avatar.png');
    }

    public function displayName(): string
    {
        return $this->name ?? $this->username;
    }

    public function lastLogin(): string
    {
        return $this->last_login_at
            ? $this->last_login_at->format('d M, Y h:i A')
            : 'Never';
    }

    /*
    |--------------------------------------------------------------------------
    | UID Generator (Alternative)
    |--------------------------------------------------------------------------
    */

    public static function generateUid(): string
    {
        do {
            $uid = strtoupper(Str::random(6));
        } while (self::where('uid', $uid)->exists());

        return $uid;
    }
}