<?php

namespace App\Modules\Hr;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Request;
use App\Models\ValidationModel;
use App\Models\User;
use App\Modules\Hr\TimeLogChangeRequest;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class TimeLog extends ValidationModel
{
    public const TYPE_IN = 'in';
    public const TYPE_OUT = 'out';

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'hr_time_log';

    /**
     * The number of models to return for pagination.
     *
     * @var int
     */
    protected $perPage = 50;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['user_id', 'type', 'time', 'new_record_request', 'holiday_id', 'lunch', 'ip_address'];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'time' => 'datetime',
        'lunch' => 'boolean',
        'new_record_request' => 'boolean',
    ];

    /**
     * The "booting" method of the model.
     */
    public static function boot(): void
    {
        parent::boot();

        static::creating(function ($model) {
            $user = Auth::user();

            if (! $model->time) {
                $model->time = now();
            }
            if (! $model->user_id && $user) {
                $model->user_id = $user->id;
            }
            
            if ($user) {
                $model->created_by = $user->id;
                $model->updated_by = $user->id;
            }
        });

        static::updating(function ($model) {
            $user = Auth::user();
            if ($user) {
                $model->updated_by = $user->id;
            } else {
                $model->updated_by = 1; // Consider a better way to handle non-auth updates
            }
        });
    }

    /**
     * Defines the relationship with the user model.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Returns all the pending change requests for the time log.
     */
    public function pending_change_requests(): HasMany
    {
        return $this->hasMany(TimeLogChangeRequest::class, 'time_log_id')->where('completed', 0);
    }

    /**
     * Applies filters to retrieve the last record for the current date.
     */
    public function scopeLastRecord(Builder $query): Builder
    {
        return $query->own()->today()->whereNull('holiday_id')->where('time', '<=', now())->orderBy('time', 'desc');
    }

    /**
     * Applies filters to retrieve the last record that has the lunch flag.
     */
    public function scopeLastlunchRecord(Builder $query): Builder
    {
        return $query->own()
                     ->where('lunch', '=', true)
                     ->orderBy('time', 'desc');
    }

    /**
     * Applies filters to retrieve the first record.
     */
    public function scopeFirstRecord(Builder $query): Builder
    {
        return $query->orderBy('time', 'asc');
    }

    /**
     * Add a condition to restrict the results to the logged in user.
     */
    public function scopeOwn(Builder $query): Builder
    {
        return $query->where('user_id', Auth::user()->id);
    }

    /**
     * Add a condition to restrict the results to the todays date only.
     */
    public function scopeToday(Builder $query): Builder
    {
        return $query->whereDate('time', today());
    }

    /**
     * Restrict the query to a given time interval.
     */
    public function scopePeriod(Builder $query, $startDate = null, $endDate = null): Builder
    {
        // Handle Unix timestamps (numeric strings)
        if ($startDate && is_numeric($startDate)) {
            $startDate = Carbon::createFromTimestamp($startDate);
        } else {
            $startDate = $startDate ? Carbon::parse($startDate) : Carbon::now()->subMonthsNoOverflow()->day(28)->startOfDay();
        }
        
        if ($endDate && is_numeric($endDate)) {
            $endDate = Carbon::createFromTimestamp($endDate);
        } else {
            $endDate = $endDate ? Carbon::parse($endDate) : Carbon::now()->day(27)->endOfDay();
        }

        return $query->whereBetween('time', [$startDate, $endDate]);
    }
}
