<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Carbon\Carbon;

class UserMaster extends Authenticatable
{
    use HasFactory, SoftDeletes, Notifiable;

    /* ================= TABLE CONFIG ================= */

    protected $table = 'user_master';
    protected $primaryKey = 'Usr_Id';
    public $timestamps = true;
    public $incrementing = true;

    /* ================= MASS ASSIGNMENT ================= */

    protected $fillable = [
        'Usr_Name',
        'Usr_Email',
        'Usr_Mobile',
        'Usr_Pas',
        'Usr_Role_Id',
        'Usr_Dpt_Id',
        'is_active',
        'is_locked',
        'locked_reason',
        'locked_until',
        'failed_login_attempts',
        'last_login',
        'last_password_change',
        'mfa_enabled',
        'mfa_secret',
        'session_timeout',
        'password_expiry_days'
    ];

    protected $hidden = [
        'Usr_Pas',
        'mfa_secret',
        'deleted_at'
    ];

    protected $casts = [
        'is_active'                => 'boolean',
        'is_locked'                => 'boolean',
        'locked_until'             => 'datetime',
        'failed_login_attempts'    => 'integer',
        'last_login'               => 'datetime',
        'last_password_change'     => 'datetime',
        'mfa_enabled'              => 'boolean',
        'session_timeout'          => 'integer',
        'password_expiry_days'     => 'integer',
        'created_at'               => 'datetime',
        'updated_at'               => 'datetime',
        'deleted_at'               => 'datetime'
    ];

    protected $appends = [
        'full_name',
        'account_status',
        'days_since_last_login',
        'password_expiry_days_left'
    ];

    /* ================= PASSWORD ================= */

    public function setUsrPasAttribute($value)
    {
        $this->attributes['Usr_Pas'] = Hash::make($value);
    }

    public function getAuthPassword()
    {
        return $this->Usr_Pas;
    }

    /* ================= ACCESSORS ================= */

    public function getFullNameAttribute()
    {
        return $this->Usr_Name;
    }

    public function getAccountStatusAttribute()
    {
        if ($this->trashed()) return 'Deleted';
        if (!$this->is_active) return 'Inactive';
        if ($this->is_locked) return 'Locked';
        return 'Active';
    }

    public function getDaysSinceLastLoginAttribute()
    {
        if (!$this->last_login) return 'Never';
        return $this->last_login->diffInDays(Carbon::now());
    }

    public function getPasswordExpiryDaysLeftAttribute()
    {
        if (!$this->last_password_change || !$this->password_expiry_days) {
            return null;
        }

        $expiryDate = $this->last_password_change
            ->copy()
            ->addDays($this->password_expiry_days);

        return max(0, Carbon::now()->diffInDays($expiryDate, false));
    }

    /* ================= RELATIONSHIPS ================= */

    public function role()
    {
        return $this->belongsTo(RoleMaster::class, 'Usr_Role_Id', 'Role_Id');
    }

    public function department()
    {
        return $this->belongsTo(Department::class, 'Usr_Dpt_Id', 'Dpt_Id');
    }

    /* ================= ACCOUNT LOCK ================= */

    public function isAccountLocked()
    {
        if (!$this->is_locked) return false;

        if ($this->locked_until && $this->locked_until->isPast()) {
            $this->unlockAccount();
            return false;
        }

        return true;
    }

    public function unlockAccount()
    {
        $this->update([
            'is_locked' => false,
            'locked_reason' => null,
            'locked_until' => null,
            'failed_login_attempts' => 0
        ]);
    }

    public function incrementFailedAttempts()
    {
        $this->increment('failed_login_attempts');

        if ($this->failed_login_attempts >= 5) {
            $this->lockAccount('Too many failed login attempts');
        }
    }

    public function lockAccount($reason = null)
    {
        $this->update([
            'is_locked' => true,
            'locked_reason' => $reason,
            'locked_until' => now()->addMinutes(30),
            'failed_login_attempts' => 5
        ]);
    }

    public function resetFailedAttempts()
    {
        $this->update(['failed_login_attempts' => 0]);
    }

    /* ================= PASSWORD POLICY ================= */

    public function isPasswordExpired()
    {
        if (!$this->last_password_change || !$this->password_expiry_days) {
            return true;
        }

        return $this->last_password_change
            ->copy()
            ->addDays($this->password_expiry_days)
            ->isPast();
    }

    /* ================= SCOPES ================= */

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

    public function scopeInactive($query)
    {
        return $query->where('is_active', 0)->whereNull('deleted_at');
    }

    public function scopeLocked($query)
    {
        return $query->where('is_locked', 1)
                     ->where('locked_until', '>', now())
                     ->whereNull('deleted_at');
    }

    public function scopeSearch($query, $search)
    {
        return $query->where(function ($q) use ($search) {
            $q->where('Usr_Name', 'like', "%{$search}%")
              ->orWhere('Usr_Email', 'like', "%{$search}%")
              ->orWhere('Usr_Mobile', 'like', "%{$search}%");
        });
    }
}
