<?php

namespace App\Repositories;

use App\Models\Holiday;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;

class HolidayRepository extends BaseRepository
{
    protected function resolveModel(): Model
    {
        return new Holiday();
    }

    /**
     * Get all active holidays
     */
    public function getActive(): Collection
    {
        return $this->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc')
            ->all();
    }

    /**
     * Get holidays for a year
     */
    public function getForYear(int $year): Collection
    {
        $query = $this->getQuery();
        $query->whereYear('date', $year)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc');
        $result = $query->get();
        $this->resetQuery();
        return $result;
    }

    /**
     * Get holidays for current year
     */
    public function getCurrentYear(): Collection
    {
        return $this->getForYear(now()->year);
    }

    /**
     * Get holidays by type
     */
    public function getByType(string $type): Collection
    {
        return $this->where('type', $type)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc')
            ->all();
    }

    /**
     * Get holidays for a month
     */
    public function getForMonth(int $month, int $year): Collection
    {
        $query = $this->getQuery();
        $query->whereMonth('date', $month)
            ->whereYear('date', $year)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc');
        $result = $query->get();
        $this->resetQuery();
        return $result;
    }

    /**
     * Get holidays in date range
     */
    public function getInRange(string $start, string $end): Collection
    {
        return $this->whereBetween('date', [$start, $end])
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc')
            ->all();
    }

    /**
     * Get upcoming holidays
     */
    public function getUpcoming(int $limit = 5): Collection
    {
        $query = $this->getQuery();
        $query->where('date', '>=', now()->toDateString())
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc')
            ->limit($limit);
        $result = $query->get();
        $this->resetQuery();
        return $result;
    }

    /**
     * Find by date
     */
    public function findByDate(string $date): ?Holiday
    {
        return $this->findFirstBy('date', $date);
    }

    /**
     * Check if date is a holiday
     */
    public function isHoliday(string $date): bool
    {
        $query = $this->getQuery();
        $result = $query->where('date', $date)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->exists();
        $this->resetQuery();
        return $result;
    }

    /**
     * Get public holidays for year
     */
    public function getPublicHolidays(int $year): Collection
    {
        $query = $this->getQuery();
        $query->whereYear('date', $year)
            ->where('type', Holiday::TYPE_PUBLIC)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc');
        $result = $query->get();
        $this->resetQuery();
        return $result;
    }

    /**
     * Get optional holidays for year
     */
    public function getOptionalHolidays(int $year): Collection
    {
        $query = $this->getQuery();
        $query->whereYear('date', $year)
            ->where('type', Holiday::TYPE_OPTIONAL)
            ->where('status', Holiday::STATUS_ACTIVE)
            ->orderBy('date', 'asc');
        $result = $query->get();
        $this->resetQuery();
        return $result;
    }

    /**
     * Count holidays in range
     */
    public function countInRange(string $start, string $end): int
    {
        $query = $this->getQuery();
        $result = $query->whereBetween('date', [$start, $end])
            ->where('status', Holiday::STATUS_ACTIVE)
            ->count();
        $this->resetQuery();
        return $result;
    }
}
