<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Spatie\Permission\Traits\HasRoles;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Log;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;
    use SoftDeletes;
    use HasRoles;
    protected $with = ['profile', 'jobInfo', 'bankInfo', 'manager'];
    protected $fillable = [
        'email',
        'organisation_id',
        'password',
        'user_type',
        'is_registered',
        'is_active',
        'type',
        'can_approve_payroll',
        'role',
        "is_group_account",
        "group_account_id",
        "approval_level",
    ];

    use LogsActivity;

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly(['name', 'email'])
            ->useLogName('user')
            ->logOnlyDirty()
            ->setDescriptionForEvent(fn(string $eventName) => "User with the email of '{$this->email}' has been {$eventName}")
            ->dontSubmitEmptyLogs();
    }


    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }


    // Define the permission hierarchy
    protected $permissionHierarchy = [
        'Employee' => [],
        'HR' => ['Employee'],
        'Owner' => ['HR', 'Employee'],
    ];

    //Add User_id to basis user owned tables
    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }
    public function manager(): BelongsTo
    {
        return $this->belongsTo(User::class, "manager_id");
    }
    public function bankInfo(): HasOne
    {
        return $this->hasOne(BankInfo::class);
    }
    public function jobInfo(): HasOne
    {
        return $this->hasOne(JobInfo::class);
    }
    public function userActivity(): HasOne
    {
        return $this->hasOne(UserActivity::class);
    }
    public function organisationTaxEmployee(): HasOne
    {
        return $this->hasOne(OrganisationTaxEmployee::class);
    }

    public function organisationAllowanceEmployee(): HasOne
    {
        return $this->hasOne(OrganisationEmployeeAllowance::class);
    }

    public function employeeDeduction(): HasOne
    {
        return $this->hasOne(EmployeeDeduction::class);
    }

    public function organisationEmployeePension(): HasOne
    {
        return $this->hasOne(OrganisationEmployeePension::class);
    }

    public function clockins(): HasOne
    {
        return $this->hasOne(Clockins::class);
    }

    public function userOrgPermission()
    {
        return $this->hasMany(UserOrgPermission::class);
    }
    public function managerUser()
    {
        return $this->hasMany(ManagerUser::class);
    }
    public function leaveRequest()
    {
        return $this->hasMany(LeaveRequest::class);
    }
    public function expenseApproval()
    {
        return $this->hasMany(ExpenseApproval::class);
    }
    public function employeeTransfer()
    {
        return $this->hasMany(EmployeeTransfer::class);
    }

    public function disciplinaryAction()
    {
        return $this->hasMany(DisciplinaryAction::class);
    }
    public function leavefee()
    {
        return $this->hasMany(LeaveFee::class);
    }

    public function hasPermission($orgId, $permissionName, $accessLevel)
    {
        return $this->userOrgPermission()
            ->where('org_id', $orgId)
            ->whereHas('permission', function ($query) use ($permissionName) {
                $query->where('name', $permissionName);
            })
            ->whereJsonContains('access_levels', $accessLevel)
            ->exists();
    }

    public function adminTrail(): HasOne
    {
        return $this->hasOne(AdminTrail::class);
    }


    //Define User child relationships
    public function organisation(): BelongsTo
    {
        return $this->belongsTo(Organisation::class);
    }

    public function organisationTimeSetting(): BelongsTo
    {
        return $this->belongsTo(OrganisationTimesetting::class, "time_id");
    }
}
