<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Leave extends Model
{
    use HasFactory, \App\Traits\HotelScopeTrait;

    protected $fillable = [
        'hotel_id',
        'staff_id',
        'leave_type_id',
        'start_date',
        'end_date',
        'duration',
        'reason',
        'status',
        'approved_by',
        'approver_notes',
        'approved_at',
        'rejected_by',
        'rejected_at',
        'rejection_reason',
        'emergency_contact',
        'attachment',
        'is_half_day',
        'half_day_type',
        'carry_forward_days',
        'credit_type',
        'created_by'
    ];

    protected $casts = [
        'start_date' => 'date',
        'end_date' => 'date',
        'approved_at' => 'datetime',
        'rejected_at' => 'datetime',
        'is_half_day' => 'boolean',
        'duration' => 'float',
        'carry_forward_days' => 'integer',
    ];

    /**
     * Get the staff member who applied for leave
     */
    public function staff(): BelongsTo
    {
        return $this->belongsTo(Staff::class);
    }

    /**
     * Get the leave type
     */
    public function leaveType(): BelongsTo
    {
        return $this->belongsTo(LeaveType::class);
    }

    /**
     * Get the approver
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(Staff::class, 'approved_by');
    }

    /**
     * Get the rejector
     */
    public function rejector(): BelongsTo
    {
        return $this->belongsTo(Staff::class, 'rejected_by');
    }

    /**
     * Get the creator
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(Staff::class, 'created_by');
    }

    /**
     * Scope for pending leaves
     */
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    /**
     * Scope for approved leaves
     */
    public function scopeApproved($query)
    {
        return $query->where('status', 'approved');
    }

    /**
     * Scope for rejected leaves
     */
    public function scopeRejected($query)
    {
        return $query->where('status', 'rejected');
    }

    /**
     * Scope for upcoming leaves
     */
    public function scopeUpcoming($query)
    {
        return $query->where('start_date', '>=', now())
                     ->where('status', 'approved');
    }

    /**
     * Scope for current leaves
     */
    public function scopeCurrent($query)
    {
        return $query->where('start_date', '<=', now())
                     ->where('end_date', '>=', now())
                     ->where('status', 'approved');
    }

    /**
     * Get leave status badge color
     */
    public function getStatusBadgeAttribute(): string
    {
        $statusColors = [
            'pending' => 'warning',
            'approved' => 'success',
            'rejected' => 'danger',
            'cancelled' => 'secondary'
        ];

        return $statusColors[$this->status] ?? 'secondary';
    }

    /**
     * Check if leave overlaps with another leave
     */
    public function overlapsWith($startDate, $endDate, $staffId = null): bool
    {
        $staffId = $staffId ?? $this->staff_id;

        return self::where('staff_id', $staffId)
            ->where('status', 'approved')
            ->where(function($query) use ($startDate, $endDate) {
                $query->whereBetween('start_date', [$startDate, $endDate])
                      ->orWhereBetween('end_date', [$startDate, $endDate])
                      ->orWhere(function($q) use ($startDate, $endDate) {
                          $q->where('start_date', '<=', $startDate)
                            ->where('end_date', '>=', $endDate);
                      });
            })
            ->where('id', '!=', $this->id ?? 0)
            ->exists();
    }

    /**
     * Get leave duration in words
     */
    public function getDurationInWordsAttribute(): string
    {
        if ($this->duration == 0.5) {
            return 'Half Day (' . ucfirst($this->half_day_type) . ')';
        }
        
        return $this->duration . ' day' . ($this->duration > 1 ? 's' : '');
    }
}