<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\Space;
use App\Services\AvailabilityService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class AvailabilityController extends Controller
{
    public function index(): View
    {
        $this->authorize('viewAny', Space::class);

        $spaces = Space::query()->orderBy('name')->get();
        $customers = Customer::query()->where('is_active', true)->orderBy('name')->get();

        return view('availability.index', compact('spaces', 'customers'));
    }

    public function events(Request $request, AvailabilityService $availability): JsonResponse
    {
        $this->authorize('viewAny', Space::class);

        $request->validate([
            'start' => ['required', 'date'],
            'end' => ['required', 'date', 'after:start'],
            'space_id' => ['nullable', 'integer', 'exists:spaces,id'],
            'customer_id' => ['nullable', 'integer', 'exists:customers,id'],
            'status' => ['nullable', 'string', 'max:50'],
        ]);

        $from = Carbon::parse($request->string('start')->toString());
        $to = Carbon::parse($request->string('end')->toString());

        $filters = array_filter([
            'space_id' => $request->integer('space_id') ?: null,
            'customer_id' => $request->integer('customer_id') ?: null,
            'status' => $request->string('status')->toString() ?: null,
        ]);

        return response()->json(
            $availability->calendarEvents($from, $to, $filters),
        );
    }

    public function checkAvailability(Request $request, AvailabilityService $availability): JsonResponse
    {
        $this->authorize('viewAny', Space::class);

        $request->validate([
            'space_id' => ['required', 'integer', 'exists:spaces,id'],
            'setup_start' => ['required', 'date'],
            'breakdown_end' => ['required', 'date', 'after:setup_start'],
            'ignore_booking_space_id' => ['nullable', 'integer'],
        ]);

        $setupStart = Carbon::parse($request->string('setup_start')->toString());
        $breakdownEnd = Carbon::parse($request->string('breakdown_end')->toString());

        $hasConflict = $availability->hasConflict(
            $request->integer('space_id'),
            $setupStart,
            $breakdownEnd,
            $request->integer('ignore_booking_space_id') ?: null,
        );

        return response()->json([
            'available' => ! $hasConflict,
            'status' => $hasConflict ? 'occupied' : 'available',
            'label' => $hasConflict ? 'Occupied' : 'Available',
        ]);
    }

    public function busyDates(Request $request, AvailabilityService $availability): JsonResponse
    {
        $this->authorize('viewAny', Space::class);

        $request->validate([
            'space_id' => ['required', 'integer', 'exists:spaces,id'],
            'start' => ['required', 'date'],
            'end' => ['required', 'date', 'after_or_equal:start'],
            'ignore_booking_space_id' => ['nullable', 'integer'],
        ]);

        $dates = $availability->busyDates(
            $request->integer('space_id'),
            Carbon::parse($request->string('start')->toString())->startOfDay(),
            Carbon::parse($request->string('end')->toString())->endOfDay(),
            $request->integer('ignore_booking_space_id') ?: null,
        );

        return response()->json([
            'space_id' => $request->integer('space_id'),
            'busy_dates' => $dates,
        ]);
    }
}
