<?php

namespace App\Observers\Hotel;

use App\Models\Hotel\Reservation;
use App\Models\Hotel\Room;
use App\Models\Hotel\RoomType;
use App\Models\Hotel\Season;

class RoomTypeObserver
{
    public function updated(RoomType $type): void
    {
      //* Update Rooms (Seasons & Rates Configuration)
        // Control Data
            $rt_configuration = $type->tr_seasons ?? [];
            $rt_pax_configuration = $type->tr_pax_seasons ?? [];
            $rt_express_configuration = $type->tr_express_seasons ?? [];

            $using_default_seasons = (bool) ($rt_configuration['using_default'] ?? true); // Is room type using default season?
            $rooms = Room::where('roomType_id', $type->id)->get(); // Linked rooms to room type

        // Preloaded Data
            $default_season = null;
            $seasons_map = collect();
            $season_price_Ids = [];
            $rt_pax_price_map = [];
            $rt_express_price_map = [];

            // Get selected seasons data
            if ($using_default_seasons) {
                $default_season = Season::find(1);
            } else {
                $seasonIds = collect($rt_configuration['other_seasons'] ?? [])
                    ->pluck('season_id')->filter()
                    ->unique()->values()->all();

                if (!empty($seasonIds))
                    $seasons_map = Season::whereIn('id', $seasonIds)->get()->keyBy('id');
            }

            // Map each other seasons data as season_id => season_price structure
                // Season Pricing
                foreach (($rt_configuration['other_seasons'] ?? []) as $other_season) {
                    $sid = $other_season['season_id'];
                    if ($sid)
                        $season_price_Ids[$sid] = (float)($other_season['season_price'] ?? 0.0);
                }

                // Pax Pricing
                foreach (($rt_pax_configuration['other_seasons'] ?? []) as $paxSeason) {
                    $sid = $paxSeason['season_id'] ?? null;
                    if ($sid)
                        $rt_pax_price_map[$sid] = $paxSeason['season_pax_pricing'] ?? [];
                }

                // Express Pricing
                foreach (($rt_express_configuration['other_seasons'] ?? []) as $expressSeason) {
                    $sid = $expressSeason['season_id'] ?? null;
                    if ($sid)
                        $rt_express_price_map[$sid] = $expressSeason['season_express_pricing'] ?? [];
                }

        // Define new Rooms Configuration
            foreach ($rooms as $room) {
              // Extract room configuration
                $room_configuration = $room->room_prices ?? [];

              // Define Basic structure
                $shared_structure = [
                    'using_default_prices'  => $room_configuration['using_default_prices']  ?? true,
                    'using_default_periods' => $room_configuration['using_default_periods'] ?? true,
                    'room_prices'           => [],
                ];

                $new_season_configuration = [...$shared_structure];
                $new_pax_configuration = [...$shared_structure];
                $new_express_configuration = [...$shared_structure];

              // Is the first season indicated by the configuration of the room and the type of room not the default?
                try {
                    $is_custom_seasons_using = ($room_configuration['room_prices'][0]["season_id"] != 1) && !$rt_configuration['using_default'];
                } catch (\Throwable $th) {
                    $is_custom_seasons_using = false;
                }

                if ($is_custom_seasons_using) {
                  // Keep periods and names, only update prices
                    foreach (($room_configuration['room_prices'] ?? []) as $room_season) {
                        $sid = $room_season['season_id'];

                        if ($sid && isset($season_price_Ids[$sid])) {
                          // Define shared Data
                            $shared_data = [
                                'season_id'    => $sid,
                                'season_name'  => (string)($room_season['season_name'] ?? ''),
                                'is_cyclic'  => (string)($room_season['is_cyclic'] ?? ''),
                                'cycle_type'  => (string)($room_season['cycle_type'] ?? ''),
                                'periods'      => (array)($room_season['periods'] ?? []),
                            ];

                          // Update columns
                            $new_season_configuration['room_prices'][] = [ // Season
                                ...$shared_data,
                                'season_price' => (float)$season_price_Ids[$sid],
                            ];
                            $new_pax_configuration['room_prices'][] = [ // PAX
                                ...$shared_data,
                                'season_pax_pricing' => $rt_pax_price_map[$sid] ?? [],
                            ];
                            $new_express_configuration['room_prices'][] = [ // Express
                                ...$shared_data,
                                'season_express_pricing' => $rt_express_price_map[$sid] ?? [],
                            ];
                        }
                    }

                } else {
                    if ($using_default_seasons) {
                      // Use Default Season
                        $shared_data = [
                            'season_id'    => 1,
                            'season_name'  => $default_season->s_name,
                            'is_cyclic'  => $default_season->is_cyclic,
                            'cycle_type'  => $default_season->cycle_type,
                            'periods'      => $default_season->s_periods['periods'],
                        ];

                        $new_season_configuration['room_prices'][] = [ // Season
                            ...$shared_data,
                            'season_price' => (float)($rt_configuration['default_season_price'] ?? 0.0),
                        ];
                        $new_pax_configuration['room_prices'][] = [ // PAX
                            ...$shared_data,
                            'season_pax_pricing' => $rt_pax_configuration['default_season_pax_pricing'] ?? [],
                        ];
                        $new_express_configuration['room_prices'][] = [ // Express
                            ...$shared_data,
                            'season_express_pricing' => $rt_express_configuration['default_season_express_pricing'] ?? [],
                        ];
                    } else {
                      // Use parent seasons
                        foreach (($rt_configuration['other_seasons'] ?? []) as $ts) {
                          // Ensure Season and Get Data
                            $sid = $ts['season_id'];
                                if (!$sid) continue;

                            $custom_season = $seasons_map->get($sid); // Get actual season from preloaded season

                          // Define shared Data
                            $shared_data = [
                                'season_id'    => $sid,
                                'season_name'  => $ts['season_name'],
                                'is_cyclic'    => $custom_season->is_cyclic,
                                'cycle_type'   => $custom_season->cycle_type,
                                'periods'      => $custom_season->s_periods['periods'],
                            ];

                          // Update columns
                            $new_season_configuration['room_prices'][] = [ // Season
                                ...$shared_data,
                                'season_price' => (float)($ts['season_price'] ?? 0.0),
                            ];
                            $new_pax_configuration['room_prices'][] = [ // PAX
                                ...$shared_data,
                                'season_pax_pricing' => $rt_pax_price_map[$sid] ?? [],
                            ];
                            $new_express_configuration['room_prices'][] = [ // Express
                                ...$shared_data,
                                'season_express_pricing' => $rt_express_price_map[$sid] ?? [],
                            ];
                        }
                    }
                }

                // Update Room Configuration
                $room->additional_pax_charge = $type->additional_pax_charge;
                $room->express_checkout_penalty = $type->express_checkout_penalty;

                $room->room_prices = $new_season_configuration;
                $room->room_pax_prices = $new_pax_configuration;
                $room->room_express_prices = $new_express_configuration;
                $room->saveQuietly(); // Avoid Launch Other Observers
            }
    }

    public function deleting(RoomType $type): void
    {
        // Avoid Delete Control Types
        if (in_array($type->id, [1, 2]))
            throw new \Exception("Control Types cannot be Deleted.");

        // Save Relationships
        Reservation::where('roomType_id', $type->id)->update(['roomType_id' => 2, 'room_id' => 1]);
    }
}
