<?php

namespace Modules\Bms\Http\Controllers\Api;

use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Modules\Bms\Entities\BmsArea;
use Modules\Bms\Entities\BmsHall;
use Modules\Bms\Entities\BmsHallAvailability;
use Modules\Bms\Services\Contracts\MediaServiceContract;

/**
 * Public read-only catalog for the client funnel: reference data, hall list
 * (summary + cover image) and hall detail (galleries, packages, add-ons).
 */
class CatalogController extends ApiController
{
    /** Reference data for the wizard (areas, F&B levels, venue types). */
    public function reference(Request $request)
    {
        $businessId = $this->publicBusinessId($request);

        return $this->ok([
            'areas' => BmsArea::where('business_id', $businessId)->where('is_active', true)
                ->orderBy('sort_order')->get(['id', 'name', 'name_ar']),
            'fnb_levels' => collect(['high_tea', 'drinks_only', 'set_menu', 'open_buffet', 'custom'])
                ->map(fn ($k) => ['key' => $k, 'label' => __('bms::lang.' . $k)]),
            'venue_types' => [
                ['key' => 'open',   'label' => __('bms::lang.open_air')],
                ['key' => 'closed', 'label' => __('bms::lang.closed')],
                ['key' => 'both',   'label' => __('bms::lang.both')],
            ],
        ]);
    }

    /** Active halls (summary cards). Covers prefer the requested event type. */
    public function halls(Request $request, MediaServiceContract $media)
    {
        $businessId = $this->publicBusinessId($request);
        $eventType = $request->input('event_type');

        $halls = BmsHall::where('business_id', $businessId)
            ->where('is_active', true)
            ->with(['venue:id,name,name_ar', 'media' => fn ($q) => $q->where('type', 'image')->orderByDesc('is_cover')->orderBy('sort_order')])
            ->orderBy('sort_order')
            ->get();

        return $this->ok([
            'halls' => $halls->map(fn ($h) => $this->hallSummary($h, $media, $eventType))->values(),
        ]);
    }

    /** Full hall profile: galleries, packages, add-ons. */
    public function hall(Request $request, MediaServiceContract $media, int $id)
    {
        $businessId = $this->publicBusinessId($request);

        $hall = BmsHall::where('business_id', $businessId)->where('is_active', true)
            ->with([
                'venue:id,name,name_ar,address,city',
                'area:id,name,name_ar',
                'media' => fn ($q) => $q->orderByDesc('is_cover')->orderBy('sort_order'),
                'packages' => fn ($q) => $q->where('is_active', true)->orderBy('sort_order'),
                'packages.items' => fn ($q) => $q->orderBy('sort_order'),
                'addons' => fn ($q) => $q->where('is_available', true),
            ])
            ->find($id);

        if (! $hall) {
            return $this->fail('Not found', 404);
        }

        $presenter = app(\Modules\Bms\Services\Catalog\PackagePresenter::class);

        return $this->ok([
            'hall' => array_merge($this->hallSummary($hall, $media), [
                'description'    => $hall->description,
                'description_ar' => $hall->description_ar,
                'area'        => $hall->area ? ['id' => $hall->area->id, 'name' => $hall->area->name, 'name_ar' => $hall->area->name_ar] : null,
                'gallery'     => $hall->media->map(fn ($m) => [
                    'type'       => $m->type,
                    'url'        => $m->url ?: $media->url($m->disk, $m->path),
                    'thumbnail'  => $m->thumbnail_path ? $media->url($m->disk, $m->thumbnail_path) : null,
                    'title'      => $m->title,
                    'event_type' => $m->event_type,
                ])->values(),
                'packages'    => $hall->packages->map(fn ($p) => [
                    'id'               => $p->id,
                    'name'             => $p->name,
                    'name_ar'          => $p->name_ar,
                    'description'      => $p->description,
                    'description_ar'   => $p->description_ar,
                    'fnb_level'        => $p->fnb_level,
                    'price'            => (float) $p->price,
                    'price_per_person' => (bool) $p->price_per_person,
                    'min_pax'          => $p->min_pax,
                    'max_pax'          => $p->max_pax,
                    'items'            => $presenter->present($p->items),
                ])->values(),
                'addons'      => $hall->addons->map(fn ($a) => [
                    'id'       => $a->id,
                    'name'     => $a->name,
                    'name_ar'  => $a->name_ar,
                    'category' => $a->category,
                    'price'    => (float) ($a->pivot->price_override ?? $a->price),
                    'unit'     => $a->unit,
                    // Marketing media inherited from the linked product (image/video/360).
                    'media'    => $a->product_id
                                    ? app(\Modules\Bms\Services\Catalog\ProductPresentation::class)->media((int) $a->product_id)
                                    : [],
                ])->values(),
            ]),
        ]);
    }

    /**
     * Month availability for a hall (client funnel calendar): which dates are
     * taken (booked/tentative/hold/blocked) so the client can see open days for
     * their chosen date or flexible month.
     */
    public function hallAvailability(Request $request, int $id)
    {
        $businessId = $this->publicBusinessId($request);
        BmsHall::where('business_id', $businessId)->findOrFail($id);

        $month = preg_match('/^\d{4}-\d{2}$/', (string) $request->input('month')) ? $request->input('month') : now()->format('Y-m');
        $start = Carbon::parse($month . '-01')->startOfMonth();
        $end = (clone $start)->endOfMonth();

        $taken = [];
        BmsHallAvailability::where('hall_id', $id)
            ->whereBetween('date', [$start->toDateString(), $end->toDateString()])
            ->whereIn('status', ['booked', 'tentative', 'hold', 'blocked'])
            ->get(['date', 'status'])
            ->each(function ($r) use (&$taken) {
                $taken[Carbon::parse($r->date)->toDateString()] = $r->status;
            });

        return $this->ok([
            'month'      => $month,
            'days'       => $end->day,
            'first_dow'  => (int) $start->dayOfWeek, // 0=Sun
            'today'      => now()->toDateString(),
            'taken'      => $taken,
        ]);
    }

    protected function hallSummary(BmsHall $hall, MediaServiceContract $media, ?string $eventType = null): array
    {
        // Prefer a cover that matches the requested occasion, else fall back.
        $images = $hall->media->where('type', 'image');
        $cover = ($eventType ? $images->firstWhere('event_type', $eventType) : null) ?: $images->first() ?: $hall->media->first();

        return [
            'id'           => $hall->id,
            'name'         => $hall->name,
            'name_ar'      => $hall->name_ar,
            'venue'        => $hall->venue ? ['id' => $hall->venue->id, 'name' => $hall->venue->name, 'name_ar' => $hall->venue->name_ar] : null,
            'capacity_min' => $hall->capacity_min,
            'capacity_max' => $hall->capacity_max,
            'venue_type'   => $hall->venue_type,
            'fnb_levels'   => $hall->fnb_levels ?? [],
            'min_budget'   => (float) $hall->min_budget,
            'base_price'   => $hall->base_price !== null ? (float) $hall->base_price : null,
            'features'     => $hall->features ?? [],
            'cover_url'    => $cover ? ($cover->url ?: $media->url($cover->disk, $cover->path)) : null,
        ];
    }
}
