<?php

namespace Modules\HR\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Accounts\Models\Traits\HasAccountingPeriod;
use Modules\Accounts\Models\Traits\HasFiscalYear;
use Modules\Employee\Models\Traits\HasEmployee;
use Modules\Employee\Models\Traits\HasShift;

// use Modules\HR\Database\Factories\AttendanceFactory;

class Attendance extends Model
{
    use HasFactory, HasEmployee, HasShift, HasFiscalYear, HasAccountingPeriod;

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'employee_id',
        'shift_id',
        'date',
        'check_in',
        'check_out',
        'worked_minutes',
        'late_minutes',
        'early_exit_minutes',
        'overtime_minutes',
        'status',
        'is_locked',
        'fiscal_year_id',
        'accounting_period_id',
    ];

    // protected static function newFactory(): AttendanceFactory
    // {
    //     // return AttendanceFactory::new();
    // }

    /**
     * [Scope] employee name / emp_number দিয়ে search
     */
    public function scopeSearch(Builder $query, ?string $search): Builder
    {
        if (! $search) {
            return $query;
        }

        return $query->whereHas('employee', function ($q) use ($search) {
            $q->where('name', 'like', "%{$search}%")
                ->orWhere('emp_number', 'like', "%{$search}%");
        });
    }

    public function scopeForEmployee(Builder $query, ?int $employeeId): Builder
    {
        return $employeeId ? $query->where('employee_id', $employeeId) : $query;
    }

    public function scopeForDepartment(Builder $query, ?int $departmentId): Builder
    {
        if (! $departmentId) {
            return $query;
        }

        return $query->whereHas('employee', fn($q) => $q->where('department_id', $departmentId));
    }

    public function scopeForDesignation(Builder $query, ?int $designationId): Builder
    {
        if (! $designationId) {
            return $query;
        }

        return $query->whereHas('employee', fn($q) => $q->where('designation_id', $designationId));
    }

    public function scopeForShift(Builder $query, ?int $shiftId): Builder
    {
        return $shiftId ? $query->where('shift_id', $shiftId) : $query;
    }

    /**
     * [Scope] status filter - single value অথবা array দুটোই handle করে
     */
    public function scopeFilterStatus(Builder $query, $status): Builder
    {
        if (! $status) {
            return $query;
        }

        return is_array($status)
            ? $query->whereIn('status', $status)
            : $query->where('status', $status);
    }

    public function scopeLocked(Builder $query, ?bool $isLocked): Builder
    {
        return is_null($isLocked) ? $query : $query->where('is_locked', $isLocked);
    }

    public function scopeHasOvertime(Builder $query, ?bool $hasOvertime): Builder
    {
        if (is_null($hasOvertime)) {
            return $query;
        }

        return $hasOvertime
            ? $query->where('overtime_minutes', '>', 0)
            : $query->where('overtime_minutes', '=', 0);
    }

    public function scopeMinLateMinutes(Builder $query, ?int $minutes): Builder
    {
        return $minutes ? $query->where('late_minutes', '>=', $minutes) : $query;
    }

    public function scopeDateBetween(Builder $query, ?string $fromDate, ?string $toDate): Builder
    {
        if ($fromDate) {
            $query->whereDate('date', '>=', $fromDate);
        }

        if ($toDate) {
            $query->whereDate('date', '<=', $toDate);
        }

        return $query;
    }

    public function scopeForFiscalYear(Builder $query, ?int $fiscalYearId): Builder
    {
        return $fiscalYearId ? $query->where('fiscal_year_id', $fiscalYearId) : $query;
    }

    public function scopeForAccountingPeriod(Builder $query, ?int $accountingPeriodId): Builder
    {
        return $accountingPeriodId ? $query->where('accounting_period_id', $accountingPeriodId) : $query;
    }
}
