<?php

namespace App\Filament\Widgets;

use App\Enums\OverrideScope;
use App\Models\ProfitCenterSupplierSchedule;
use App\Models\DeliveryCalendarOverride;
use App\Models\WorkCalendar;
use App\Enums\WorkDayType;
use App\Services\DeliveryCalendarService;
use App\Services\WorkCalendarService;
use Illuminate\Support\Carbon;
use Saade\FilamentFullCalendar\Widgets\FullCalendarWidget;
use Illuminate\Database\Eloquent\Model;
use Filament\Actions\Action;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\TextInput;
use Livewire\Attributes\On;

class DeliveryCalendarWidget extends FullCalendarWidget
{
    /**
     * @var ProfitCenterSupplierSchedule|null
     */
    public Model | int | string | null $record = null;

    public ?int $supplierId = null;

    public ?int $profitCenterId = null;

    /** Következő szállítási nap dátuma (YYYY-MM-DD formátum), kék kiemeléshez. */
    public ?string $nextDeliveryDate = null;

    /**
     * Inaktív (nem választható) napok listája.
     *
     * @var array<string>
     */
    protected array $inactiveDates = [];

    public function mount(): void
    {
        $this->loadRecordFromFilter();
    }

    public function updatedSupplierId(): void
    {
        $this->loadRecordFromFilter();
        $this->refreshRecords();
    }

    public function updatedProfitCenterId(): void
    {
        $this->loadRecordFromFilter();
        $this->refreshRecords();
    }

    #[On('calendar-filter-changed')]
    public function onFilterChanged(?int $supplierId, ?int $profitCenterId): void
    {
        $this->supplierId = $supplierId;
        $this->profitCenterId = $profitCenterId;
        $this->record = null;
        $this->loadRecordFromFilter();
        $this->refreshRecords();
    }

    #[On('next-delivery-date-changed')]
    public function onNextDeliveryDateChanged(?string $date): void
    {
        $this->nextDeliveryDate = $date;
        $this->refreshRecords();
    }

    protected function loadRecordFromFilter(): void
    {
        if ($this->record instanceof ProfitCenterSupplierSchedule) {
            return;
        }

        if ($this->supplierId && $this->profitCenterId) {
            $this->record = ProfitCenterSupplierSchedule::where('supplier_id', $this->supplierId)
                ->where('profit_center_id', $this->profitCenterId)
                ->first();
            return;
        }

        if (!$this->record) {
            $this->record = ProfitCenterSupplierSchedule::first();
        }
    }

    public function fetchEvents(array $info): array
    {
        if (!($this->record instanceof ProfitCenterSupplierSchedule)) {
            $this->loadRecordFromFilter();
        }

        if (!$this->record) {
            $this->dispatch('calendar-events-done');
            return $this->getDemoEvents($info);
        }

        /** @var DeliveryCalendarService $service */
        $service = app(DeliveryCalendarService::class);
        /** @var WorkCalendarService $workService */
        $workService = app(WorkCalendarService::class);

        $start = Carbon::parse($info['start']);
        $end = Carbon::parse($info['end']);

        $events = [];

        // 1. Szállítási napok – zöld háttér
        $deliveryDates = $service->getAvailableDeliveryDates(
            $this->record->profitCenter,
            $this->record->supplier,
            $start,
            $end
        );

        foreach ($deliveryDates as $date) {
            $events[] = [
                'id' => 'delivery-' . $date->format('Y-m-d'),
                'title' => '',
                'start' => $date->format('Y-m-d'),
                'end' => $date->addDay()->format('Y-m-d'),
                'allDay' => true,
                'display' => 'background',
                'backgroundColor' => '#4CAF50',
                'extendedProps' => ['type' => 'delivery'],
            ];
        }

        // 2. Munkaszüneti napok – piros háttér
        $workCalendarEntries = $workService->getCalendarEntries($start, $end);
        foreach ($workCalendarEntries as $entry) {
            if ($entry->type === WorkDayType::Holiday) {
                $events[] = [
                    'id' => 'holiday-' . $entry->date->format('Y-m-d'),
                    'title' => '',
                    'start' => $entry->date->format('Y-m-d'),
                    'end' => $entry->date->copy()->addDay()->format('Y-m-d'),
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#EF4444',
                    'extendedProps' => ['type' => 'holiday'],
                ];
            } elseif ($entry->type === WorkDayType::WorkingDay) {
                // 3. Áthelyezett munkanapok – narancssárga háttér
                $events[] = [
                    'id' => 'transferred-' . $entry->date->format('Y-m-d'),
                    'title' => '',
                    'start' => $entry->date->format('Y-m-d'),
                    'end' => $entry->date->copy()->addDay()->format('Y-m-d'),
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#F59E0B',
                    'extendedProps' => ['type' => 'transferred'],
                ];
            }
        }

        // 4. Hétvégék – szürke háttér (inaktív napok)
        $current = $start->copy();
        while ($current->lte($end)) {
            if ($current->isWeekend()) {
                $events[] = [
                    'id' => 'weekend-' . $current->format('Y-m-d'),
                    'title' => '',
                    'start' => $current->format('Y-m-d'),
                    'end' => $current->copy()->addDay()->format('Y-m-d'),
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#E5E7EB',
                    'extendedProps' => ['type' => 'inactive'],
                ];
            }
            $current->addDay();
        }

        // 5. Következő szállítási nap – kék háttér
        if ($this->nextDeliveryDate) {
            $nextDate = Carbon::parse($this->nextDeliveryDate);
            if ($nextDate->between($start, $end)) {
                $events[] = [
                    'id' => 'next-delivery-' . $nextDate->format('Y-m-d'),
                    'title' => '',
                    'start' => $nextDate->format('Y-m-d'),
                    'end' => $nextDate->copy()->addDay()->format('Y-m-d'),
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#3B82F6',
                    'extendedProps' => ['type' => 'next-delivery'],
                ];
            }
        }

        $this->dispatch('calendar-events-done');
        return $events;
    }

    /**
     * Demo események generálása, ha nincs valós adat.
     *
     * @param array{start: string, end: string} $info
     * @return array<int, array<string, mixed>>
     */
    protected function getDemoEvents(array $info): array
    {
        $start = Carbon::parse($info['start']);
        $end = Carbon::parse($info['end']);
        $events = [];

        $current = $start->copy();
        while ($current->lte($end)) {
            $dayOfWeek = $current->dayOfWeek;
            $dayOfMonth = $current->day;
            $dateStr = $current->format('Y-m-d');
            $nextDateStr = $current->copy()->addDay()->format('Y-m-d');

            if ($current->isWeekend()) {
                // Hétvégék – szürke háttér (inaktív)
                $events[] = [
                    'id' => 'weekend-' . $dateStr,
                    'title' => '',
                    'start' => $dateStr,
                    'end' => $nextDateStr,
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#E5E7EB',
                    'extendedProps' => ['type' => 'inactive'],
                ];
            } elseif ($dayOfWeek === Carbon::MONDAY || $dayOfWeek === Carbon::WEDNESDAY || $dayOfWeek === Carbon::FRIDAY) {
                // Hétfő, szerda, péntek – zöld háttér (szállítási napok)
                $events[] = [
                    'id' => 'delivery-' . $dateStr,
                    'title' => '',
                    'start' => $dateStr,
                    'end' => $nextDateStr,
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#4CAF50',
                    'extendedProps' => ['type' => 'delivery'],
                ];
            }

            // Néhány speciális nap bemutatóként
            if ($dayOfMonth === 15) {
                // Minden hónap 15-e – narancssárga (áthelyezett munkanap)
                $events[] = [
                    'id' => 'special-orange-' . $dateStr,
                    'title' => '',
                    'start' => $dateStr,
                    'end' => $nextDateStr,
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#F59E0B',
                    'extendedProps' => ['type' => 'transferred'],
                ];
            }

            if ($dayOfMonth === 1) {
                // Minden hónap 1-je – piros (ünnepnap)
                $events[] = [
                    'id' => 'special-red-' . $dateStr,
                    'title' => '',
                    'start' => $dateStr,
                    'end' => $nextDateStr,
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#EF4444',
                    'extendedProps' => ['type' => 'holiday'],
                ];
            }

            if ($dayOfMonth === 10 || $dayOfMonth === 20) {
                // 10-e és 20-a – kék (megrendelési határidő)
                $events[] = [
                    'id' => 'special-blue-' . $dateStr,
                    'title' => '',
                    'start' => $dateStr,
                    'end' => $nextDateStr,
                    'allDay' => true,
                    'display' => 'background',
                    'backgroundColor' => '#3B82F6',
                    'extendedProps' => ['type' => 'deadline'],
                ];
            }

            $current->addDay();
        }

        return $events;
    }

    public function onDateSelect(string $start, ?string $end, bool $allDay, ?array $view, ?array $resource): void
    {
        $this->mountAction('manageOverride', [
            'date' => Carbon::parse($start)->format('Y-m-d'),
        ]);
    }

    public function onEventClick(array $event): void
    {
        $date = data_get($event, 'start');

        if (!$date) {
            return;
        }

        $this->mountAction('manageOverride', [
            'date' => Carbon::parse($date)->format('Y-m-d'),
        ]);
    }

    protected function headerActions(): array
    {
        return [
            Action::make('manageOverride')
                ->label('Felülbírálás kezelése')
                ->modalHeading(fn (array $arguments) => "Szállítás felülbírálása" . (isset($arguments['date']) ? ": " . $arguments['date'] : ""))
                ->form(fn (array $arguments) => [
                    Placeholder::make('info')
                        ->hiddenLabel()
                        ->content('A háttérben látható naptárban egyszerre több hónapot is áttekinthet. Itt egy konkrét nap módosítását végezheti el.'),
                    \Filament\Forms\Components\DatePicker::make('date')
                        ->label('Dátum')
                        ->required()
                        ->default($arguments['date'] ?? null)
                        ->disabled(fn () => isset($arguments['date']))
                        ->dehydrated(),
                    Toggle::make('is_delivery_day')
                        ->label('Szállítási nap?')
                        ->default(function () use ($arguments) {
                            $date = $arguments['date'] ?? null;
                            if (!$date) {
                                return true;
                            }

                            $override = DeliveryCalendarOverride::where('supplier_id', $this->record->supplier_id)
                                ->whereDate('date', $date)
                                ->where('override_scope', OverrideScope::ProfitCenter->value)
                                ->where('profit_center_id', $this->record->profit_center_id)
                                ->first();

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

                            return app(DeliveryCalendarService::class)->isDeliveryDay(
                                $this->record->profitCenter,
                                $this->record->supplier,
                                Carbon::parse($date)
                            );
                        }),
                    TextInput::make('description')
                        ->label('Indoklás / Megjegyzés')
                        ->default(fn () => isset($arguments['date'])
                            ? DeliveryCalendarOverride::where('supplier_id', $this->record->supplier_id)
                                ->whereDate('date', $arguments['date'])
                                ->where('override_scope', OverrideScope::ProfitCenter->value)
                                ->where('profit_center_id', $this->record->profit_center_id)
                                ->first()?->description
                            : null
                        ),
                ])
                ->action(function (array $data) {
                    DeliveryCalendarOverride::updateOrCreate(
                        [
                            'supplier_id' => $this->record->supplier_id,
                            'override_scope' => OverrideScope::ProfitCenter->value,
                            'profit_center_id' => $this->record->profit_center_id,
                            'date' => $data['date'],
                        ],
                        [
                            'is_delivery_day' => (bool) $data['is_delivery_day'],
                            'description' => $data['description'],
                        ]
                    );

                    $this->refreshRecords();
                }),
        ];
    }

    public function config(): array
    {
        return [
            'initialView' => 'multiMonthYear',
            'views' => [
                'multiMonthYear' => [
                    'duration' => ['months' => 6],
                ],
            ],
            'multiMonthMaxColumns' => 6,
            'headerToolbar' => [
                'left' => 'prev,next today',
                'center' => 'title',
                'right' => 'multiMonthYear',
            ],
            'locale' => 'hu',
            'firstDay' => 1,
            'height' => 'auto',
            'contentHeight' => 'auto',
            'selectable' => true,
            'editable' => false,
            'dayMaxEvents' => false,
            'fixedWeekCount' => false,
        ];
    }
}
