<?php

namespace App\Services;

use App\Enums\OverrideScope;
use App\Models\DeliveryCalendarOverride;
use App\Models\ProfitCenter;
use App\Models\ProfitCenterSupplierSchedule;
use App\Models\Supplier;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;

class DeliveryCalendarService extends ServiceBase
{
    public function __construct(
        protected WorkCalendarService $workCalendarService
    ) {
    }

    /**
     * Eldönti, hogy egy adott Profit Center, Beszállító és Dátum kombináció esetén van-e szállítás.
     *
     * A felülbírálás kiértékelése 3 szinten történik (legspecifikusabbtól az általánosig):
     *   1. Profitcenter-specifikus override (csak erre az 1 PC-re)
     *   2. Régió-specifikus override (a PC városához/régiójához tartozó)
     *   3. Általános override (az összes PC-re vonatkozó)
     * Ha egyetlen szinten sem található override, folytatódik a normál kiértékelés.
     */
    public function isDeliveryDay(ProfitCenter $pc, Supplier $supplier, Carbon $date): bool
    {
        $date = $date->startOfDay();

        // 1. Prioritás: Profitcenter-specifikus felülbírálás
        $override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
            ->whereDate('date', $date)
            ->where('override_scope', OverrideScope::ProfitCenter->value)
            ->where('profit_center_id', $pc->id)
            ->first();

        if ($override) {
            return $override->is_delivery_day;
        }

        // PC-hez rendelt szállítási sablon lekérése (2. és 5. prioritáshoz egyaránt szükséges)
        $assignment = ProfitCenterSupplierSchedule::where('profit_center_id', $pc->id)
            ->where('supplier_id', $supplier->id)
            ->with('deliverySchedule')
            ->first();

        // 2. Prioritás: DeliverySchedule-specifikus felülbírálás (a PC-hez rendelt szállítási sablon alapján)
        if ($assignment && $assignment->delivery_schedule_id) {
            $override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
                ->whereDate('date', $date)
                ->where('override_scope', OverrideScope::Region->value)
                ->where('delivery_schedule_id', $assignment->delivery_schedule_id)
                ->first();

            if ($override) {
                return $override->is_delivery_day;
            }
        }

        // 3. Prioritás: Általános felülbírálás (minden PC-re vonatkozik)
        $override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
            ->whereDate('date', $date)
            ->where('override_scope', OverrideScope::General->value)
            ->first();

        if ($override) {
            return $override->is_delivery_day;
        }

        // 4. Prioritás: Hivatalos ünnepnap (WorkCalendar)
        // Ha aznap nem hivatalos munkanap van, akkor nincs szállítás (kivéve ha az 1-3. pont felülbírálta).
        if (! $this->workCalendarService->isWorkDay($date)) {
            return false;
        }

        // 5. Prioritás: Heti sablon (Schedule)
        if (! $assignment || ! $assignment->deliverySchedule || ! $assignment->deliverySchedule->is_active) {
            return false;
        }

        $dayOfWeek = strtolower($date->format('l')); // 'monday', 'tuesday', etc.

        return (bool) $assignment->deliverySchedule->{$dayOfWeek};
    }

    /**
     * Visszaadja az elérhető szállítási napokat egy adott időszakban.
     *
     * @return Collection<Carbon>
     */
    public function getAvailableDeliveryDates(ProfitCenter $pc, Supplier $supplier, Carbon $start, Carbon $end): Collection
    {
        $dates = collect();
        $current = $start->copy()->startOfDay();
        $end = $end->copy()->startOfDay();

        while ($current <= $end) {
            if ($this->isDeliveryDay($pc, $supplier, $current)) {
                $dates->push($current->copy());
            }
            $current->addDay();
        }

        return $dates;
    }
}
