<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\ParkingSlot;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\ParkingLevel;
use App\Models\ParkingType;

class ParkingSlotController extends Controller
{
    /**
     * Display a listing of the parking slots.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function index()
    {
        $parkingSlots = ParkingSlot::all();

        return response()->json([
            'status' => 'success',
            'data' => $parkingSlots,
        ], 200);
    }

    /**
     * Display the specified parking slot.
     *
     * @param  int  $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function show($id)
    {
        $parkingSlot = ParkingSlot::find($id);

        if (!$parkingSlot) {
            return response()->json([
                'status' => 'error',
                'message' => 'Parking slot not found',
            ], 404);
        }

        return response()->json([
            'status' => 'success',
            'data' => $parkingSlot,
        ], 200);
    }

    /**
     * Store a newly created parking slot(s) in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function store(Request $request)
    {
        // Validate the request
        $validator = Validator::make($request->all(), [
            'PL_Id' => 'required|exists:parking_levels,PL_Id',
            'PT_ID' => 'required|exists:parking_types,PT_ID',
            'PS_No' => 'required|integer|min:1', // Allow any number of slots
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $numSlots = (int) $request->PS_No;
        $createdSlots = [];

        // Fetch Level_Desc and Type_Desc
        $parkingLevel = ParkingLevel::find($request->PL_Id);
        $parkingType = ParkingType::find($request->PT_ID);

        if (!$parkingLevel || !$parkingType) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid parking level or type',
            ], 422);
        }

        // Generate prefix for PS_No (e.g., 'L1-R' for Level 1, Regular)
        $levelPrefix = 'L' . $parkingLevel->PL_Id; // e.g., 'L1'
        $typePrefix = strtoupper(substr($parkingType->Type_Desc, 0, 1)); // e.g., 'R' for Regular
        $prefix = "{$levelPrefix}-{$typePrefix}"; // e.g., 'L1-R'

        // Find the highest existing slot number for this level and type
        $lastSlot = ParkingSlot::where('PS_No', 'like', "{$prefix}-%")
            ->orderBy('PS_No', 'desc')
            ->first();

        $startNumber = $lastSlot ? (int) substr($lastSlot->PS_No, -5) + 1 : 1;

        // Use transaction for atomicity
        try {
            DB::transaction(function () use ($request, $numSlots, $prefix, $startNumber, &$createdSlots) {
                for ($i = 0; $i < $numSlots; $i++) {
                    $slotNumber = str_pad($startNumber + $i, 5, '0', STR_PAD_LEFT); // e.g., '00001', '00002'
                    $psNo = "{$prefix}-{$slotNumber}"; // e.g., 'L1-R-00001'

                    // Check for uniqueness
                    if (ParkingSlot::where('PS_No', $psNo)->exists()) {
                        throw new \Exception("Slot number {$psNo} already exists");
                    }

                    $slot = ParkingSlot::create([
                        'PL_Id' => $request->PL_Id,
                        'PT_ID' => $request->PT_ID,
                        'PS_No' => $psNo,
                    ]);
                    $createdSlots[] = $slot;
                }
            });

            return response()->json([
                'status' => 'success',
                'message' => "$numSlots parking slots created successfully",
                'data' => $createdSlots,
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to create parking slots: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Update the specified parking slot in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function update(Request $request, $id)
    {
        $parkingSlot = ParkingSlot::find($id);

        if (!$parkingSlot) {
            return response()->json([
                'status' => 'error',
                'message' => 'Parking slot not found',
            ], 404);
        }

        // Validate the request
        $validator = Validator::make($request->all(), [
            'PL_Id' => 'required|exists:parking_levels,PL_Id',
            'PT_ID' => 'required|exists:parking_types,PT_ID',
            'PS_No' => 'required|string|regex:/^L[0-9]+-[A-Z]-[0-9]{5}$/', // e.g., 'L1-R-00001'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }

        // Check if PS_No is unique (excluding the current slot)
        if (ParkingSlot::where('PS_No', $request->PS_No)->where('PS_ID', '!=', $id)->exists()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Parking slot number already exists',
            ], 422);
        }

        $parkingSlot->update([
            'PL_Id' => $request->PL_Id,
            'PT_ID' => $request->PT_ID,
            'PS_No' => $request->PS_No,
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Parking slot updated successfully',
            'data' => $parkingSlot,
        ], 200);
    }

    /**
     * Remove the specified parking slot from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function destroy($id)
    {
        $parkingSlot = ParkingSlot::find($id);

        if (!$parkingSlot) {
            return response()->json([
                'status' => 'error',
                'message' => 'Parking slot not found',
            ], 404);
        }

        $parkingSlot->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Parking slot deleted successfully',
        ], 200);
    }
}
