<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;

class Employee extends Model implements AuditableContract
{
    use HasFactory;
    use SoftDeletes;
    use Auditable;

    protected $fillable = [
        'employee_code',
        'file_number',
        'first_name',
        'last_name',
        'user_id',
        'department_id',
        'salary_structure',
        'grade_level',
        'salary_step',
        'phone',
        'date_of_birth',
        'gender',
        'marital_status',
        'union_name',
        'employment_status',
        'date_of_join',
    ];

    protected function casts(): array
    {
        return [
            'date_of_birth' => 'date',
            'date_of_join' => 'date',
            'salary_step' => 'integer',
        ];
    }

    /**
     * Full display name. Source data stores the whole name in last_name;
     * this concatenation is safe whether or not first_name is populated.
     */
    public function getFullNameAttribute(): string
    {
        return trim(($this->first_name ?? '').' '.($this->last_name ?? ''));
    }

    public function department(): BelongsTo
    {
        return $this->belongsTo(Department::class);
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function bankAccount(): HasOne
    {
        return $this->hasOne(BankAccount::class)->where('is_primary', true);
    }

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

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

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

    /**
     * Refresh this employee's cached current grade columns from the grade
     * timeline in force today, then persist. Called after recording a grading
     * (and by the apply-due command for future-dated entries).
     */
    public function syncCurrentGrade(): bool
    {
        $current = $this->gradings()->inForceOn(now()->toDateString())->first();
        if ($current === null) {
            return false;
        }

        $unchanged = $this->salary_structure === $current->salary_structure
            && $this->grade_level === $current->grade_level
            && (int) $this->salary_step === (int) $current->salary_step;
        if ($unchanged) {
            return false;
        }

        $this->forceFill([
            'salary_structure' => $current->salary_structure,
            'grade_level' => $current->grade_level,
            'salary_step' => $current->salary_step,
        ])->saveQuietly();

        return true;
    }
}
