<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use App\Models\Traits\HasScopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * Employee Attendance Model
 *
 * Tracks daily attendance records including check-in/out times,
 * break times, working hours, overtime, and half-day status.
 */
class EmployeeAttendance extends Model
{
    use HasFactory, SoftDeletes, HasAuditFields, HasScopes;

    protected $table = 'employee_attendances';

    /**
     * Attendance status constants
     */
    public const STATUS_PRESENT = 'PR';
    public const STATUS_ABSENT = 'AB';
    public const STATUS_HALF_DAY = 'HD';
    public const STATUS_ON_LEAVE = 'OL';
    public const STATUS_WEEK_OFF = 'WO';
    public const STATUS_HOLIDAY = 'HO';

    /**
     * Shift constants
     */
    public const SHIFT_GENERAL = 'GS';
    public const SHIFT_NIGHT = 'NS';
    public const SHIFT_MORNING = 'MS';
    public const SHIFT_EVENING = 'ES';

    protected $fillable = [
        'date',
        'employee_id',
        'employee_name',
        'shift',
        'check_in',
        'break_out',
        'break_in',
        'check_out',
        'first_half',
        'second_half',
        'late_in',
        'early_out',
        'working_hours',
        'ot_hours',
        'shortage_hours',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'date' => 'date:Y-m-d',
        'check_in' => 'datetime:H:i:s',
        'break_out' => 'datetime:H:i:s',
        'break_in' => 'datetime:H:i:s',
        'check_out' => 'datetime:H:i:s',
        'working_hours' => 'decimal:2',
        'ot_hours' => 'decimal:2',
        'shortage_hours' => 'decimal:2',
    ];

    /**
     * Column configuration for HasScopes trait
     */
    protected string $dateColumn = 'date';

    // =========================================================================
    // RELATIONSHIPS
    // =========================================================================

    public function employee()
    {
        return $this->belongsTo(EmployeeDetails::class, 'employee_id', 'employee_id');
    }

    // =========================================================================
    // SCOPES
    // =========================================================================

    /**
     * Scope to filter by employee ID
     */
    public function scopeForEmployee(Builder $query, string $employeeId): Builder
    {
        return $query->where('employee_id', $employeeId);
    }

    /**
     * Scope to filter by shift
     */
    public function scopeOnShift(Builder $query, string $shift): Builder
    {
        return $query->where('shift', $shift);
    }

    /**
     * Scope to filter present records
     */
    public function scopePresent(Builder $query): Builder
    {
        return $query->where(function ($q) {
            $q->where('first_half', self::STATUS_PRESENT)
              ->orWhere('second_half', self::STATUS_PRESENT);
        });
    }

    /**
     * Scope to filter absent records
     */
    public function scopeAbsent(Builder $query): Builder
    {
        return $query->where('first_half', self::STATUS_ABSENT)
                     ->where('second_half', self::STATUS_ABSENT);
    }

    /**
     * Scope to filter by month and year
     */
    public function scopeForMonth(Builder $query, int $month, int $year): Builder
    {
        return $query->whereMonth('date', $month)
                     ->whereYear('date', $year);
    }

    /**
     * Scope to filter records with overtime
     */
    public function scopeWithOvertime(Builder $query): Builder
    {
        return $query->where('ot_hours', '>', 0);
    }

    /**
     * Scope to filter records with late arrivals
     */
    public function scopeLateArrivals(Builder $query): Builder
    {
        return $query->whereNotNull('late_in')
                     ->where('late_in', '!=', '');
    }

    /**
     * Scope to filter records with early departures
     */
    public function scopeEarlyDepartures(Builder $query): Builder
    {
        return $query->whereNotNull('early_out')
                     ->where('early_out', '!=', '');
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    /**
     * Get all valid attendance statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_PRESENT,
            self::STATUS_ABSENT,
            self::STATUS_HALF_DAY,
            self::STATUS_ON_LEAVE,
            self::STATUS_WEEK_OFF,
            self::STATUS_HOLIDAY,
        ];
    }

    /**
     * Get all valid shifts
     */
    public static function getShifts(): array
    {
        return [
            self::SHIFT_GENERAL,
            self::SHIFT_NIGHT,
            self::SHIFT_MORNING,
            self::SHIFT_EVENING,
        ];
    }

    /**
     * Check if fully present (both halves)
     */
    public function isFullyPresent(): bool
    {
        return $this->first_half === self::STATUS_PRESENT
            && $this->second_half === self::STATUS_PRESENT;
    }

    /**
     * Check if fully absent (both halves)
     */
    public function isFullyAbsent(): bool
    {
        return $this->first_half === self::STATUS_ABSENT
            && $this->second_half === self::STATUS_ABSENT;
    }

    /**
     * Check if half day
     */
    public function isHalfDay(): bool
    {
        return ($this->first_half === self::STATUS_PRESENT && $this->second_half === self::STATUS_ABSENT)
            || ($this->first_half === self::STATUS_ABSENT && $this->second_half === self::STATUS_PRESENT);
    }

    /**
     * Check if late
     */
    public function isLate(): bool
    {
        return !empty($this->late_in);
    }

    /**
     * Check if left early
     */
    public function leftEarly(): bool
    {
        return !empty($this->early_out);
    }

    /**
     * Get attendance summary
     */
    public function getSummaryAttribute(): string
    {
        if ($this->isFullyPresent()) {
            return 'Present';
        }
        if ($this->isFullyAbsent()) {
            return 'Absent';
        }
        if ($this->isHalfDay()) {
            return 'Half Day';
        }
        return 'Partial';
    }
}
