<?php

namespace App\Http\Controllers;

use App\Models\Accommodation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use DB;
use App\Traits\DeleteModelTrait;
use Carbon\Carbon;

class AccommodationController extends Controller
{
    use DeleteModelTrait;

    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $accommodations = Accommodation::where('status', true)
            ->orderBy('room_name')
            ->get()
            ->map(function ($accommodation) {
                return [
                    'id' => $accommodation->id,
                    'room_name' => $accommodation->room_name,
                    'primary_photo' => $accommodation->primary_photo,
                    'price_fbu' => $accommodation->price_fbu,
                    'price_usd' => $accommodation->price_usd,
                    'description' => $accommodation->description,
                    'featured' => $accommodation->featured,
                ];
            });

        return Inertia::render('Accommodations', [
            'accommodations' => $accommodations,
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        try {
            DB::beginTransaction();

            $validatedData = $request->validate([
                'room_name' => 'nullable|string|max:255',
                'room_number' => 'nullable|string|max:50',
                'room_category' => 'required|string|max:100',
                'price_fbu' => 'required|numeric|min:0.01',
                'price_usd' => 'required|numeric|min:0.01',
                'price_eur' => 'nullable|numeric|min:0.01',
                'description' => 'required|min:20',
                'full_description' => 'nullable|min:20',
                'size' => 'nullable|string|max:100',
                'bed_type' => 'nullable|string|max:100',
                'view' => 'nullable|string|max:100',
                'amenities' => 'nullable|array',
                'amenities.*' => 'string|max:100',
                'gallery' => 'nullable|array',
                'gallery.*' => 'string',
                'status' => 'required|boolean',
                'featured' => 'required|boolean',
                'primary_photo' => 'required|string',
            ]);

            // Auto-populate room_name from room_category if not provided
            if (empty($validatedData['room_name'])) {
                $validatedData['room_name'] = $validatedData['room_category'];
            }

            // Ensure amenities and gallery are arrays, default to empty array if null
            $validatedData['amenities'] = $validatedData['amenities'] ?? [];
            
            // Handle gallery - check raw input first
            $galleryInput = $request->input('gallery');
            if (is_array($galleryInput) && !empty($galleryInput)) {
                // Filter out empty values
                $validatedData['gallery'] = array_values(array_filter($galleryInput, function($item) {
                    return !empty($item) && is_string($item);
                }));
            } else {
                $validatedData['gallery'] = [];
            }
            
            $accommodation = new Accommodation;
            $accommodation->room_name = $validatedData['room_name'];
            $accommodation->room_number = $validatedData['room_number'] ?? null;
            $accommodation->room_category = $validatedData['room_category'] ?? null;
            $accommodation->price_fbu = $validatedData['price_fbu'];
            $accommodation->price_usd = $validatedData['price_usd'];
            $accommodation->price_eur = $validatedData['price_eur'] ?? null;
            $accommodation->description = $validatedData['description'];
            $accommodation->full_description = $validatedData['full_description'] ?? null;
            $accommodation->size = $validatedData['size'] ?? null;
            $accommodation->bed_type = $validatedData['bed_type'] ?? null;
            $accommodation->view = $validatedData['view'] ?? null;
            $accommodation->amenities = $validatedData['amenities'] ?? [];
            $accommodation->gallery = $validatedData['gallery'] ?? [];
            $accommodation->status = $validatedData['status'];
            $accommodation->featured = $validatedData['featured'];
            $accommodation->primary_photo = $validatedData['primary_photo'];
            $accommodation->save();

            DB::commit();
            return redirect()->route('admin.accommodations')->with('success', [
                'message' => 'Accommodation added successfully',
                'check' => false
            ]);
        } catch (ValidationException $e) {
            DB::rollBack();
            return redirect()->back()
                ->withErrors($e->errors())
                ->withInput();
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', [
                'message' => 'An error occurred: ' . $e->getMessage(),
                'check' => false
            ]);
        }
    }

    /**
     * Display the specified resource.
     */
    public function show($id)
    {
        $accommodation = Accommodation::where('id', $id)->firstOrFail();

        return Inertia::render('AccommodationDetail', [
            'accommodation' => [
                'id' => $accommodation->id,
                'room_name' => $accommodation->room_name,
                'room_number' => $accommodation->room_number,
                'room_category' => $accommodation->room_category,
                'primary_photo' => $accommodation->primary_photo,
                'price_fbu' => $accommodation->price_fbu,
                'price_usd' => $accommodation->price_usd,
                'price_eur' => $accommodation->price_eur,
                'description' => $accommodation->description,
                'full_description' => $accommodation->full_description,
                'size' => $accommodation->size,
                'bed_type' => $accommodation->bed_type,
                'view' => $accommodation->view,
                'amenities' => $accommodation->amenities,
                'gallery' => $accommodation->gallery,
                'featured' => $accommodation->featured,
            ]
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit($id)
    {
        $accommodation = Accommodation::findOrFail($id);
        return response()->json([
            'id' => $accommodation->id,
            'room_name' => $accommodation->room_name,
            'room_number' => $accommodation->room_number,
            'room_category' => $accommodation->room_category,
            'primary_photo' => $accommodation->primary_photo,
            'price_fbu' => $accommodation->price_fbu,
            'price_usd' => $accommodation->price_usd,
            'price_eur' => $accommodation->price_eur,
            'description' => $accommodation->description,
            'full_description' => $accommodation->full_description,
            'size' => $accommodation->size,
            'bed_type' => $accommodation->bed_type,
            'view' => $accommodation->view,
            'amenities' => $accommodation->amenities ?? [],
            'gallery' => $accommodation->gallery ?? [],
            'status' => $accommodation->status,
            'featured' => $accommodation->featured,
            'created_at' => $accommodation->created_at,
            'updated_at' => $accommodation->updated_at,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, $id)
    {
        try {
            DB::beginTransaction();
            $validatedData = $request->validate([
                'room_name' => 'nullable|string|max:255',
                'room_number' => 'nullable|string|max:50',
                'room_category' => 'required|string|max:100',
                'price_fbu' => 'required|numeric|min:0.01',
                'price_usd' => 'required|numeric|min:0.01',
                'price_eur' => 'nullable|numeric|min:0.01',
                'description' => 'required|min:20',
                'full_description' => 'nullable|min:20',
                'size' => 'nullable|string|max:100',
                'bed_type' => 'nullable|string|max:100',
                'view' => 'nullable|string|max:100',
                'amenities' => 'nullable|array',
                'amenities.*' => 'string|max:100',
                'gallery' => 'nullable|array',
                'gallery.*' => 'string',
                'status' => 'required|boolean',
                'featured' => 'required|boolean',
                'primary_photo' => 'required|string',
            ]);

            // Auto-populate room_name from room_category if not provided
            if (empty($validatedData['room_name'])) {
                $validatedData['room_name'] = $validatedData['room_category'];
            }

            // Ensure amenities and gallery are arrays, default to empty array if null
            $validatedData['amenities'] = $validatedData['amenities'] ?? [];
            $validatedData['gallery'] = $validatedData['gallery'] ?? [];

            $accommodation = Accommodation::findOrFail($id);
            $accommodation->fill($validatedData);

            if ($accommodation->isDirty()) {
                $accommodation->save();
            }

            DB::commit();

            return Redirect::back()->with('success', [
                'message' => 'Accommodation updated successfully',
                'check' => false
            ]);
        } catch (ValidationException $e) {
            DB::rollBack();
            return redirect()->back()
                ->withErrors($e->errors())
                ->withInput();
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', [
                'message' => 'An error occurred: ' . $e->getMessage(),
                'check' => false
            ]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy($id)
    {
        return $this->deleteModel($id, new Accommodation());
    }

    public function fetchAccommodations()
    {
        $accommodations = Accommodation::orderBy('created_at', 'desc')->get();
        return Inertia::render('accommodations/Accommodation', [
            'accommodations' => $accommodations->map(function ($accommodation) {
                return [
                    'id' => $accommodation->id ?? null,
                    'room_name' => $accommodation->room_name ?? '',
                    'room_category' => $accommodation->room_category ?? $accommodation->room_name ?? '',
                    'status' => (int) ($accommodation->getRawOriginal('status') ?? 0),
                    'featured' => (int) ($accommodation->getRawOriginal('featured') ?? 0),
                    'price_fbu' => $accommodation->price_fbu ?? null,
                    'price_usd' => $accommodation->price_usd ?? null,
                    'primary_photo' => $accommodation->primary_photo ?? null,
                    'created_at' => $accommodation->created_at ?? null,
                ];
            }),
        ]);
    }

    public function uploadImage(Request $request)
    {
        $request->validate([
            'file' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:5048',
        ]);

        $path = $request->file('file')->store('accommodation-images', 'public');
        $filename = basename($path);

        return response()->json(['filename' => 'accommodation-images/' . $filename]);
    }

    public function uploadMultipleImages(Request $request)
    {
        $request->validate([
            'files.*' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:5048',
        ]);

        $filenames = [];
        if ($request->hasFile('files')) {
            foreach ($request->file('files') as $file) {
                $path = $file->store('accommodation-images', 'public');
                $filenames[] = 'accommodation-images/' . basename($path);
            }
        }

        return response()->json(['filenames' => $filenames]);
    }

    /**
     * Check availability of accommodation for given dates
     */
    public function checkAvailability(Request $request, $id)
    {
        $request->validate([
            'check_in' => 'required|date',
            'check_out' => 'required|date|after:check_in',
        ]);

        $accommodation = Accommodation::findOrFail($id);
        $isAvailable = $accommodation->isAvailable($request->check_in, $request->check_out);

        return response()->json([
            'available' => $isAvailable,
            'message' => $isAvailable 
                ? 'Room is available for the selected dates' 
                : 'Room is not available for the selected dates'
        ]);
    }

    /**
     * Get available rooms for an accommodation category for given dates
     */
    public function getAvailableRooms(Request $request, $id)
    {
        $request->validate([
            'check_in' => 'required|date',
            'check_out' => 'required|date|after:check_in',
        ]);

        $accommodation = Accommodation::with('pricingRule')->findOrFail($id);
        $availableRooms = $accommodation->getAvailableRooms($request->check_in, $request->check_out);

        return response()->json([
            'rooms' => $availableRooms->map(function($room) use ($accommodation) {
                return [
                    'id' => $room->id,
                    'room_number' => $room->room_number,
                    'display_name' => $room->display_name,
                    'accommodation_id' => $room->accommodation_id,
                    'category' => $accommodation->room_category ?? $accommodation->room_name,
                ];
            }),
            'pricing_rule' => $accommodation->pricingRule ? [
                'base_price_bif' => $accommodation->pricingRule->base_price_bif,
                'base_price_usd' => $accommodation->pricingRule->base_price_usd,
                'base_price_eur' => $accommodation->pricingRule->base_price_eur,
                'additional_adult_bif' => $accommodation->pricingRule->additional_adult_bif,
                'additional_adult_usd' => $accommodation->pricingRule->additional_adult_usd,
                'additional_adult_eur' => $accommodation->pricingRule->additional_adult_eur,
                'child_surcharge_bif' => $accommodation->pricingRule->child_surcharge_bif,
                'child_surcharge_usd' => $accommodation->pricingRule->child_surcharge_usd,
                'child_surcharge_eur' => $accommodation->pricingRule->child_surcharge_eur,
            ] : null,
        ]);
    }

    /**
     * Get all accommodations with available room counts for given dates
     */
    public function getAllAvailableAccommodations(Request $request)
    {
        $request->validate([
            'check_in' => 'required|date',
            'check_out' => 'required|date|after:check_in',
        ]);

        // Validate dates are not in the past
        $today = Carbon::now()->startOfDay();
        $checkInDate = Carbon::parse($request->check_in)->startOfDay();
        $checkOutDate = Carbon::parse($request->check_out)->startOfDay();

        if ($checkInDate->lt($today)) {
            return response()->json([
                'error' => 'Check-in date cannot be in the past',
                'accommodations' => []
            ], 422);
        }

        if ($checkOutDate->lte($checkInDate)) {
            return response()->json([
                'error' => 'Check-out date must be after check-in date',
                'accommodations' => []
            ], 422);
        }

        $checkIn = $request->check_in;
        $checkOut = $request->check_out;

        $accommodations = Accommodation::where('status', 1)
            ->with(['rooms' => function($query) use ($checkIn, $checkOut) {
                $query->where('is_available', true);
            }])
            ->get()
            ->map(function($accommodation) use ($checkIn, $checkOut) {
                $availableRooms = $accommodation->getAvailableRooms($checkIn, $checkOut);
                $availableCount = $availableRooms->count();

                return [
                    'id' => $accommodation->id,
                    'room_name' => $accommodation->room_name,
                    'room_category' => $accommodation->room_category ?? $accommodation->room_name,
                    'primary_photo' => $accommodation->primary_photo,
                    'price_fbu' => $accommodation->price_fbu,
                    'price_usd' => $accommodation->price_usd,
                    'price_eur' => $accommodation->price_eur,
                    'available_rooms_count' => $availableCount,
                ];
            })
            ->filter(function($accommodation) {
                return $accommodation['available_rooms_count'] > 0;
            })
            ->values();

        return response()->json([
            'accommodations' => $accommodations,
        ]);
    }
}
