<?php

namespace Modules\Employee\Models;

use Illuminate\Database\Eloquent\Model;
use Modules\Core\Traits\AuditableTrait;
use Modules\Core\Traits\HasUser;
use Modules\Employee\Models\Traits\EmployeeRelationshipTrait;
use Modules\Employee\Models\Traits\GeneratesEmployeeNumber;
use Modules\Employee\Models\Traits\HasDepartment;
use Modules\Employee\Models\Traits\HasDesignation;
use Modules\Employee\Models\Traits\HasProject;
use Modules\Employee\Models\Traits\HasShift;
use Modules\HR\Models\Traits\HasAttendancePolicy;
use Modules\HR\Models\Traits\HasHolidayAllowancePolicy;
use Modules\HR\Models\Traits\HasWeekendPolicy;
use Modules\Settings\Models\Traits\HasAddresses;
use Modules\Settings\Models\Traits\HasAttachments;
use Modules\Settings\Models\Traits\HasBankInfo;

class Employee extends Model
{
    use HasUser,
        GeneratesEmployeeNumber,
        HasDepartment,
        HasDesignation,
        HasProject,
        HasAddresses,
        HasBankInfo,
        HasAttachments,
        HasAttendancePolicy,
        HasWeekendPolicy,
        HasHolidayAllowancePolicy,
        HasShift,
        AuditableTrait,
        EmployeeRelationshipTrait;

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'user_id',
        'emp_number',
        'name',
        'phone',
        'work_phone',
        'email',
        'dob',
        'nid',
        'father_name',
        'mother_name',
        'nation_id',
        'gender_id',
        'religion_id',
        'blood_id',
        'marital_status_id',
        'employment_status_id',
        'department_id',
        'designation_id',
        'project_id',
        'branch_id',
        'attendance_policy_id',
        'weekend_policy_id',
        'holiday_allowance_policy_id',
        'shift_id',
        'joined_date',
        'emp_termination_id',
        'report_to',
        'current_basic_salary',
        'cpf_active',
        'attendance_required',
        'overtime_allowed',
        'is_payroll',
        'tax_deduction',
        'image',
        'created_by',
        'updated_by',
    ];

    protected $appends = ['status'];

    protected $casts = [
        'cpf_active' => 'boolean',
        'attendance_required' => 'boolean',
        'overtime_allowed' => 'boolean',
        'is_payroll' => 'boolean',
        'tax_deduction' => 'boolean',
    ];

    public function getStatusAttribute(): string
    {
        return $this->isActive() ? 'Active' : 'Terminated';
    }

    public function scopeHasUser($query, ?bool $hasUser)
    {
        if (is_null($hasUser)) {
            return $query;
        }

        return $hasUser ? $query->whereNotNull('user_id') : $query->whereNull('user_id');
    }

    public function scopeFilterId($query, ?int $id)
    {
        return $id ? $query->where('id', $id) : $query;
    }

    public function scopeActive($query)
    {
        return $query->whereNull('emp_termination_id');
    }

    public function scopeTerminated($query)
    {
        return $query->whereNotNull('emp_termination_id');
    }

    public function scopeFilterStatus($query, string $status)
    {
        return match ($status) {
            'current' => $query->active(),
            'past'    => $query->terminated(),
            default   => $query,
        };
    }

    public function scopeFilterDepartment($query, ?int $departmentId)
    {
        return $departmentId ? $query->where('department_id', $departmentId) : $query;
    }

    public function scopeFilterDesignation($query, ?int $designationId)
    {
        return $designationId ? $query->where('designation_id', $designationId) : $query;
    }

    public function scopeFilterProject($query, ?int $projectId)
    {
        return $projectId ? $query->where('project_id', $projectId) : $query;
    }

    public function scopeFilterBranch($query, ?int $branchId)
    {
        return $branchId ? $query->where('branch_id', $branchId) : $query;
    }

    public function scopeSearch($query, ?string $search)
    {
        if (blank($search)) {
            return $query;
        }

        $like = "%{$search}%";

        return $query->where(function ($q) use ($like) {
            $q->where('name', 'LIKE', $like)
                ->orWhere('emp_number', 'LIKE', $like)
                ->orWhere('email', 'LIKE', $like)
                ->orWhere('phone', 'LIKE', $like);
        });
    }

    public function getBasicSalaryAttribute(): float
    {
        $structure = $this->currentSalaryStructure;

        if (! $structure) {
            return 0;
        }

        return $structure->basicSalaryAmount();
    }
}
