<?php

namespace App\Http\Controllers\Hotel;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Carbon\Carbon;

use App\Models\Environment\PaymentMethod;
use App\Models\Environment\Business;

use App\Models\Hotel\Agency;
use App\Models\Hotel\Regimen;
use App\Models\Hotel\Reservation;
use App\Models\Hotel\Room;
use App\Models\Hotel\RoomType;
use App\Models\Hotel\Source;
use App\Models\Hotel\Status;

class CalendarController extends Controller
{

  //* Constructor
    public function __construct() {
        $this->middleware(['auth'])->except(['publicCalendar', 'getCalendarRooms', 'createCalendarEvents']);
    }

  //* Basic CRUD
    public function index() {
       //- View Data
        $catalogs = $this->loadCalendarCatalogs();
        $render_data = $this->loadRenderData();

        return view('hotel.calendar.index', [...$catalogs, 'render_data' => $render_data]);
    }

    public function publicCalendar() {
      //- Validations
        $has_public_calendar = Business::first()->features_configuration["has_public_calendar"];
        $has_only_invoicing_system = Business::first()->features_configuration["has_only_invoicing_system"];
            if(!$has_public_calendar || $has_only_invoicing_system) return view('errors.403');

       //- View Data
        $render_data = $this->loadRenderData();

        return view('hotel.public-calendar.index', ['render_data' => $render_data]);
    }

  //* Special Functions
    public function getCalendarRooms(Request $request){
      //* Base Data
        // Revisamos si hay reservaciones con habitación asignada
        $unassigned_reservations = Reservation::where('room_id',1)->count();

        // Extract Request
        $return_express_rooms = $request->boolean("is_express");

        // Get Rooms
        $allRooms = Room::query()
            ->whereHas('roomType', function ($query) use($return_express_rooms) {
                $query->where('is_express_type', $return_express_rooms); // return express express rooms?
            })
            ->when(!$unassigned_reservations, function ($query) {  // Include Unassigned rooms when Unassigned reserves exists
                $query->where('id', '!=', 1);
            })
            ->orderByRaw('CAST(room_name AS UNSIGNED) ASC')
            ->get();

      // Build Response
        $response = []; // Data to return
        foreach ($allRooms as $room) {
            $response[] = [
                'id' => $room->id,
                'title' => $room->room_name,

                'room_floor' => $room->room_floor,
                'room_type' => $room->roomType->tr_name,
                'number_room' => $room->room_name,
                'order_number' => is_numeric($room->room_name) ? (int)$room->room_name : 9999, // Sort helper in calendar
            ];
        }

      // Return resources
        return response()->json($response);
    }

    public function createCalendarEvents(Request $request){
      //- Control Data
        $start = $request->start
            ? Carbon::parse($request->start)->subDays(15)
            : now()->startOfMonth()->subDays(15);

        $end = $request->end
            ? Carbon::parse($request->end)->addDays(15)
            : now()->endOfMonth()->addDays(15);

        // Extract Request
        $is_auth_query = auth()->check();
        $is_express = $request->boolean("is_express");

      //- Build Return
        $events = Reservation::query()
            ->select([ // Fields to Use
                'id', 'room_id', 'client_reference',
                'date_entry', 'date_departure', 'payment_status',
                'hour_entry', 'hour_departure', 'agency_id', 'client_id'
            ])
            ->with('agency:id,agency_url_image', 'client') // Load Relationships
            ->where('show_in_calendar', true)->where('is_express', $is_express) // Conditionals
            ->where(function ($query) use ($start, $end) {
                $query->whereBetween('date_entry', [$start, $end])
                    ->orWhereBetween('date_departure', [$start, $end])
                    ->orWhere(function ($q) use ($start, $end) {
                        $q->where('date_entry', '<=', $start)
                            ->where('date_departure', '>=', $end);
                    });
            })
            ->get()->map(function ($reservation) use ($is_express, $is_auth_query) { // Build Return Structure
              // Control Timeline
                $start = Carbon::parse(
                    $reservation->date_entry . ' ' . ($is_express ? $reservation->hour_entry : '00:00:00')
                )->setTimezone(config('app.timezone')) ->format('Y-m-d\TH:i:s');

                $end = Carbon::parse(
                    $reservation->date_departure . ' ' . ($is_express ? $reservation->hour_departure : '00:00:00')
                )->setTimezone(config('app.timezone')) ->format('Y-m-d\TH:i:s');

              // Build Data
                // Define Global Data
                $shared_query_data = [
                  // Render Control
                    'id' => $reservation->id,
                    'start' => $start,
                    'end' => $end,
                    'resourceId' => $reservation->room_id,

                  // Visual Control
                    'borderColor' => $reservation->payment_status,
                    // 'borderColor' => $reservation->client->segment_color. 'b3',
                    'backgroundColor' => $reservation->payment_status . '36',
                    'textColor' => '#0D6889',
                    'classNames' => ['Reservación', $reservation->id, $reservation->hour_entry, $reservation->hour_departure],
                ];

                // Define Specific Data
                if ($is_auth_query) { // For Auth Queries
                    $reserve_data = [
                      // Shared Data
                        ...$shared_query_data,

                      // Render Control
                        'title' => $reservation->client_reference,

                      // Visual Control
                        'image_url' => $reservation->agency?->agency_url_image
                            ?? Auth::user()->profile_photo
                            ?? asset('icons/close_modal.svg'),
                    ];
                } else { // For Guest Queries
                    $reserve_data = [
                      // Shared Data
                        ...$shared_query_data,

                      // Render Control
                        'title' => explode(' ', $reservation->client_reference)[0],
                    ];
                }

                return (object) $reserve_data;
            })->toArray();

        return json_encode($events);
    }

  //* Support Function
    private function loadCalendarCatalogs() : array
    {
      //- Catalogs
        $agencies = Agency::select('id', 'agency_name', 'agency_state', 'agency_url_image')->get();
        $paymentMethods = PaymentMethod::select('method_name')->get();
        $regimens = Regimen::select('id', 'regimen_name', 'regimen_status')->get();
        $sources = Source::select('id', 'source_name')->get();
        $statuses = Status::select('id', 'status_name', 'status_type')->get();

      //- Room Types
        $roomTypes = RoomType::select(
            'id',
            'tr_name',
            'is_express_type',
            'pax_room_limit',
            'minimum_express_stay'
        )->latest('id')->get();

        // Return Data
        return compact(
            'agencies', 'paymentMethods', 'regimens','sources', 'statuses',
            'roomTypes',
        );
    }

    private function loadRenderData() : object
    {
      //- Control Data
        $render_data = (object) [];

      //- Build Render Data
        // Resources Columns
        $render_data->resource_columns = [
            [
                "group" => true,
                "labelText" => __('entity_fields')['room']['floor'],
                "field" => 'room_floor'
            ],
            [
                "group" => true,
                "labelText" => __('entity_fields')['common']['type'],
                "field" => 'room_type'
            ],
            [
                "labelText" => '#',
                "field" => 'number_room'
            ]
        ];

        // Resource Label Identifier
        $render_data->resource_main_label = __('modules')['dashboard']['hotel']['rooms'];

        // Resource Order
        $render_data->resource_order = "room_floor,room_type,order_number,number_room";

      //- Return Data
        return $render_data;
    }
}
