<?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 Daily Report Model
 *
 * Tracks daily work reports including shift timings, punch records,
 * overtime, compensatory off, and manual entries.
 */
class EmployeeDailyReport extends Model
{
    use HasFactory, SoftDeletes, HasAuditFields, HasScopes;

    protected $table = 'employee_daily_reports';

    /**
     * Half status constants
     */
    public const HALF_PRESENT = 'PR';
    public const HALF_ABSENT = 'AB';
    public const HALF_LEAVE = 'LV';
    public const HALF_WEEK_OFF = 'WO';
    public const HALF_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',
        'shift',
        'in_spfid_1',
        'out_spfid_1',
        'in_spfid_2',
        'out_spfid_2',
        'first_half',
        'second_half',
        'late_in',
        'early_out',
        'hourly_paid_leave',
        'hourly_unpaid_leave',
        'over_time',
        'auth_ot',
        'auth_coff',
        'work_hours',
        'man_entry',
        'reason',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'date' => 'date:Y-m-d',
        'hourly_paid_leave' => 'decimal:2',
        'hourly_unpaid_leave' => 'decimal:2',
        'over_time' => 'decimal:2',
        'auth_ot' => 'decimal:2',
        'auth_coff' => 'decimal:2',
        'work_hours' => 'decimal:2',
        'man_entry' => 'boolean',
    ];

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

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

    public function employeeDetails()
    {
        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 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 manual entries
     */
    public function scopeManualEntries(Builder $query): Builder
    {
        return $query->where('man_entry', true);
    }

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

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

    /**
     * Scope to filter records with compensatory off
     */
    public function scopeWithCompOff(Builder $query): Builder
    {
        return $query->where('auth_coff', '>', 0);
    }

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

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

    /**
     * Get all valid half statuses
     */
    public static function getHalfStatuses(): array
    {
        return [
            self::HALF_PRESENT,
            self::HALF_ABSENT,
            self::HALF_LEAVE,
            self::HALF_WEEK_OFF,
            self::HALF_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
     */
    public function isFullyPresent(): bool
    {
        return $this->first_half === self::HALF_PRESENT
            && $this->second_half === self::HALF_PRESENT;
    }

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

    /**
     * Check if manual entry
     */
    public function isManualEntry(): bool
    {
        return (bool) $this->man_entry;
    }

    /**
     * Check if has overtime
     */
    public function hasOvertime(): bool
    {
        return $this->over_time > 0;
    }

    /**
     * Get total leave hours (paid + unpaid)
     */
    public function getTotalLeaveHoursAttribute(): float
    {
        return ($this->hourly_paid_leave ?? 0) + ($this->hourly_unpaid_leave ?? 0);
    }

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