<?php

namespace App\Http\Controllers\Agency;

use App\Http\Controllers\Controller;
use App\Models\DayTour\DayTourDate;
use App\Models\InternationalTour\InternationalTourDate;
use App\Models\Resource;
use App\Models\ResourceSchedule;
use App\Models\Sale\SaleItem;
use App\Models\Tour\TourDate;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;

class AgencyCalendarController extends Controller
{
    /** Tur tipi → [tarih modeli, tur ilişkisi, tarih kolonu, renk, url anahtarı] */
    private const DEP_TYPES = [
        'cultural' => [TourDate::class, 'tour', 'start_date', '#6366f1', 'Kültür Turu'],
        'international' => [InternationalTourDate::class, 'tour', 'start_date', '#0ea5e9', 'Yurt Dışı Turu'],
        'day_tour' => [DayTourDate::class, 'dayTour', 'tour_date', '#0d9488', 'Günübirlik Tur'],
    ];

    /** Satış kalemi (kişiye özel tarih) rengi */
    private const SALE_COLOR = '#e11d48';

    /** Kaynak plan tipi renkleri */
    private const SCHED_COLORS = [
        'tour_assignment' => '#10b981',
        'block' => '#ef4444',
        'maintenance' => '#f59e0b',
        'leave' => '#8b5cf6',
    ];

    private function agencyId(): int
    {
        return Auth::user()->currentAgencyId();
    }

    public function index()
    {
        $agencyId = $this->agencyId();
        $resources = Resource::where('agency_id', $agencyId)
            ->where('is_active', true)
            ->orderBy('type')->orderBy('name')
            ->get(['id', 'name', 'type']);

        return view('agency.calendar.index', [
            'resources' => $resources,
            'depTypes' => collect(self::DEP_TYPES)->map(fn ($x) => ['color' => $x[3], 'label' => $x[4]]),
            'schedColors' => self::SCHED_COLORS,
            'saleColor' => self::SALE_COLOR,
        ]);
    }

    /** FullCalendar JSON feed — turlar + kaynak planları birleşik. */
    public function events(Request $request)
    {
        $agencyId = $this->agencyId();
        $start = Carbon::parse($request->get('start', now()->startOfMonth()));
        $end = Carbon::parse($request->get('end', now()->endOfMonth()));
        $source = $request->get('source', 'all'); // all | tours | resources

        $events = [];

        if ($source !== 'resources') {
            $events = array_merge($events, $this->departureEvents($agencyId, $start, $end, $request));
        }
        if ($source !== 'tours') {
            $events = array_merge($events, $this->resourceEvents($agencyId, $start, $end, $request));
        }
        if ($source === 'all' || $source === 'sales') {
            $events = array_merge($events, $this->saleItemEvents($agencyId, $start, $end, $request));
        }

        return response()->json($events);
    }

    /**
     * Satış kalemlerine elle girilen tarihler (kişiye özel satışlar, transfer,
     * konaklama…). Tur kalemleri özel kalkışa dönüştüğü için (departure_id dolu)
     * burada atlanır — aksi halde takvimde aynı iş iki kez görünürdü.
     */
    private function saleItemEvents(int $agencyId, Carbon $start, Carbon $end, Request $request): array
    {
        if ($request->filled('tour_type') || $request->filled('resource_id') || $request->filled('schedule_type') || $request->filled('resource_type')) {
            return []; // tur/kaynak filtresi aktifken satış kalemleri gösterilmez
        }

        $items = SaleItem::query()
            ->whereNotNull('start_date')
            ->whereNull('departure_id')
            ->whereBetween('start_date', [$start->toDateString(), $end->toDateString()])
            ->whereHas('sale', fn ($q) => $q->where('agency_id', $agencyId)
                ->whereNotIn('status', ['cancelled', 'refunded']))
            ->with('sale.customer')
            ->get();

        $events = [];
        foreach ($items as $item) {
            $sale = $item->sale;
            $sDate = Carbon::parse($item->start_date);
            $eDate = $item->end_date ? Carbon::parse($item->end_date) : $sDate->copy();
            $sTime = $this->timeStr($item->start_time);
            $eTime = $this->timeStr($item->end_time);

            if ($sDate->isSameDay($eDate) && $sTime) {
                $startStr = $sDate->toDateString() . 'T' . $sTime;
                $endStr = $eTime ? $sDate->toDateString() . 'T' . $eTime : null;
                $allDay = false;
            } else {
                $startStr = $sDate->toDateString();
                $endStr = $eDate->copy()->addDay()->toDateString();
                $allDay = true;
            }

            $customer = $sale?->customer?->full_name;

            $events[] = [
                'title' => '🧾 ' . $item->name . ($customer ? ' · ' . $customer : ''),
                'start' => $startStr,
                'end' => $endStr,
                'allDay' => $allDay,
                'backgroundColor' => self::SALE_COLOR,
                'borderColor' => self::SALE_COLOR,
                'extendedProps' => [
                    'kind' => 'sale_item',
                    'qvUrl' => $sale ? route('agency.sales.quick-view', $sale) : null,
                    'typeLabel' => 'Satış Kalemi',
                ],
            ];
        }

        return $events;
    }

    /** Tur kalkışları. */
    private function departureEvents(int $agencyId, Carbon $start, Carbon $end, Request $request): array
    {
        $filterType = $request->get('tour_type');
        $events = [];

        foreach (self::DEP_TYPES as $key => [$class, $rel, $dateCol, $color, $label]) {
            if ($filterType && $filterType !== $key) {
                continue;
            }

            $dates = $class::whereHas($rel, fn ($q) => $q->where('agency_id', $agencyId))
                ->where('is_active', true)
                ->whereBetween($dateCol, [$start->toDateString(), $end->toDateString()])
                ->with($rel)
                ->get();

            foreach ($dates as $date) {
                $tour = $date->{$rel};
                $isDayTour = $date instanceof DayTourDate;
                $sDate = Carbon::parse($isDayTour ? $date->tour_date : $date->start_date);
                $eDate = $isDayTour ? $sDate->copy() : Carbon::parse($date->end_date ?? $date->start_date);
                $sTime = $this->timeStr($date->start_time ?? null);
                $eTime = $this->timeStr($date->end_time ?? null);

                $singleDay = $sDate->isSameDay($eDate);
                if ($singleDay && $sTime) {
                    $startStr = $sDate->toDateString() . 'T' . $sTime;
                    $endStr = $eTime ? $sDate->toDateString() . 'T' . $eTime : null;
                    $allDay = false;
                } else {
                    $startStr = $sDate->toDateString();
                    $endStr = $eDate->copy()->addDay()->toDateString(); // FC allDay end exclusive
                    $allDay = true;
                }

                // Kişiye özel kalkışlar (satış kartında elle girilen tarihten üretilen)
                // normal kalkışlardan ayırt edilebilsin
                $isPrivate = (bool) ($date->is_private ?? false);

                $events[] = [
                    'title' => ($isPrivate ? '🔒 ' : '🚌 ') . ($tour->name ?? 'Tur'),
                    'start' => $startStr,
                    'end' => $endStr,
                    'allDay' => $allDay,
                    'backgroundColor' => $isPrivate ? self::SALE_COLOR : $color,
                    'borderColor' => $isPrivate ? self::SALE_COLOR : $color,
                    'extendedProps' => [
                        'kind' => 'departure',
                        'qvUrl' => route('agency.operations.quick-view', [$key, $date->id]),
                        'typeLabel' => $isPrivate ? $label . ' · Kişiye Özel' : $label,
                    ],
                ];
            }
        }

        return $events;
    }

    /** Kaynak planları (atama / bloke / bakım / izin). */
    private function resourceEvents(int $agencyId, Carbon $start, Carbon $end, Request $request): array
    {
        $query = ResourceSchedule::byAgency($agencyId)
            ->with('resource')
            ->inDateRange($start->toDateString(), $end->toDateString());

        if ($request->filled('resource_id')) {
            $query->forResource($request->resource_id);
        }
        if ($request->filled('schedule_type')) {
            $query->where('schedule_type', $request->schedule_type);
        }
        if ($request->filled('resource_type')) {
            $query->whereHas('resource', fn ($q) => $q->where('type', $request->resource_type));
        }

        $events = [];
        foreach ($query->get() as $s) {
            // Tur ataması: ön atama (amber) / kesin atama (yeşil); diğerleri sabit renk.
            $color = $s->schedule_type === 'tour_assignment'
                ? $s->assignment_color
                : (self::SCHED_COLORS[$s->schedule_type] ?? '#64748b');
            $sDate = Carbon::parse($s->start_date);
            $eDate = Carbon::parse($s->end_date);
            $singleDay = $sDate->isSameDay($eDate);
            $sTime = $this->timeStr($s->start_time);
            $eTime = $this->timeStr($s->end_time);

            if ($singleDay && $sTime) {
                $startStr = $sDate->toDateString() . 'T' . $sTime;
                $endStr = $eTime ? $sDate->toDateString() . 'T' . $eTime : null;
                $allDay = false;
            } else {
                $startStr = $sDate->toDateString();
                $endStr = $eDate->copy()->addDay()->toDateString();
                $allDay = true;
            }

            $statusPrefix = $s->schedule_type === 'tour_assignment' ? '[' . $s->assignment_status_label . '] ' : '';

            $events[] = [
                'title' => $statusPrefix . ($s->resource->name ?? 'Kaynak') . ' · ' . $s->title,
                'start' => $startStr,
                'end' => $endStr,
                'allDay' => $allDay,
                'backgroundColor' => $color,
                'borderColor' => $color,
                'extendedProps' => [
                    'kind' => 'resource',
                    'resourceId' => $s->resource_id,
                    'scheduleType' => $s->schedule_type,
                    'assignmentStatus' => $s->assignment_status,
                    'assignmentStatusLabel' => $s->schedule_type === 'tour_assignment' ? $s->assignment_status_label : null,
                ],
            ];
        }

        return $events;
    }

    private function timeStr($val): ?string
    {
        if (!$val) {
            return null;
        }
        if ($val instanceof \DateTimeInterface) {
            return $val->format('H:i:s');
        }
        try {
            return Carbon::parse($val)->format('H:i:s');
        } catch (\Throwable $e) {
            return null;
        }
    }
}
