<?php

namespace App\Http\Controllers;

use App\Models\SocUnit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SocUnitController extends Controller
{
    public function index()
    {
        $units = SocUnit::with(['block' => function ($query) {
            $query->with(['division' => function ($query) {
                $query->with('society');
            }]);
        }, 'unitType'])->get();
        return response()->json([
            'status' => 'success',
            'message' => 'Society units retrieved successfully',
            'data' => $units
        ], 200);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'SB_Id' => 'nullable|exists:soc_block,SB_Id',
            'UT_Id' => 'nullable|exists:unit_types,UT_Id',
            'Unit_No' => 'required|integer|min:1|max:10',
            'Start_Floor' => 'required|integer|min:1',
            'End_Floor' => 'required|integer|min:1|gte:Start_Floor',
        ], [
            'SB_Id.exists' => 'The selected block does not exist.',
            'UT_Id.exists' => 'The selected unit type does not exist.',
            'Unit_No.required' => 'Unit number is required.',
            'Unit_No.integer' => 'Unit number must be a valid number.',
            'Unit_No.min' => 'Unit number must be at least 1.',
            'Unit_No.max' => 'Unit number cannot exceed 10.',
            'Start_Floor.required' => 'Start floor number is required.',
            'Start_Floor.integer' => 'Start floor number must be a valid number.',
            'Start_Floor.min' => 'Start floor number must be at least 1.',
            'End_Floor.required' => 'End floor number is required.',
            'End_Floor.integer' => 'End floor number must be a valid number.',
            'End_Floor.min' => 'End floor number must be at least 1.',
            'End_Floor.gte' => 'End floor number must be greater than or equal to start floor number.',
        ]);

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

        try {
            $data = $validator->validated();
            $units = [];

            DB::beginTransaction();

            $unitNo = $data['Unit_No'];
            $startFloor = $data['Start_Floor'];
            $endFloor = $data['End_Floor'];

            // Validate floor range (1 to 100)
            if ($startFloor < 1 || $endFloor > 100) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Floor numbers must be between 1 and 100.'
                ], 422);
            }

            // Check if any unit will be duplicated before creating
            $duplicateUnits = [];
            for ($floor = $startFloor; $floor <= $endFloor; $floor++) {
                $generatedUnitNo = ($floor * 100) + $unitNo;
                if (SocUnit::where('SB_Id', $data['SB_Id'] ?? null)
                    ->where('Unit_No', $generatedUnitNo)
                    ->exists()) {
                    $duplicateUnits[] = $generatedUnitNo;
                }
            }

            if (!empty($duplicateUnits)) {
                DB::rollBack();
                return response()->json([
                    'status' => 'error',
                    'message' => 'Cannot create units. The following unit numbers already exist: ' . implode(', ', $duplicateUnits)
                ], 422);
            }

            // Create units for each floor in the range
            for ($floor = $startFloor; $floor <= $endFloor; $floor++) {
                $generatedUnitNo = ($floor * 100) + $unitNo;

                $unit = SocUnit::create([
                    'SB_Id' => $data['SB_Id'] ?? null,
                    'UT_Id' => $data['UT_Id'] ?? null,
                    'Unit_No' => $generatedUnitNo,
                ]);
                $unit->load(['block' => function ($query) {
                    $query->with(['division' => function ($query) {
                        $query->with('society');
                    }]);
                }, 'unitType']);
                $units[] = $unit;
            }

            DB::commit();

            return response()->json([
                'status' => 'success',
                'message' => 'Society unit(s) created successfully',
                'data' => $units
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error creating society unit(s): ' . $e->getMessage(), [
                'request' => $request->all(),
                'exception' => $e->getTraceAsString()
            ]);
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to create society unit(s): ' . $e->getMessage(),
                'error_code' => $e->getCode()
            ], 500);
        }
    }

    public function show($id)
    {
        $unit = SocUnit::with(['block' => function ($query) {
            $query->with(['division' => function ($query) {
                $query->with('society');
            }]);
        }, 'unitType'])->find($id);
        if (!$unit) {
            return response()->json([
                'status' => 'error',
                'message' => 'Society unit not found'
            ], 404);
        }

        return response()->json([
            'status' => 'success',
            'message' => 'Society unit retrieved successfully',
            'data' => $unit
        ], 200);
    }

    public function update(Request $request, $id)
    {
        $unit = SocUnit::find($id);
        if (!$unit) {
            return response()->json([
                'status' => 'error',
                'message' => 'Society unit not found'
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'SB_Id' => 'nullable|exists:soc_block,SB_Id',
            'UT_Id' => 'nullable|exists:unit_types,UT_Id',
            'Unit_No' => 'nullable|integer|min:1',
        ], [
            'SB_Id.exists' => 'The selected block does not exist.',
            'UT_Id.exists' => 'The selected unit type does not exist.',
            'Unit_No.integer' => 'Unit number must be a valid number.',
            'Unit_No.min' => 'Unit number must be at least 1.',
        ]);

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

        try {
            $unit->update($request->only(['SB_Id', 'UT_Id', 'Unit_No']));
            $unit->load(['block' => function ($query) {
                $query->with(['division' => function ($query) {
                    $query->with('society');
                }]);
            }, 'unitType']);
            return response()->json([
                'status' => 'success',
                'message' => 'Society unit updated successfully',
                'data' => $unit
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error updating society unit: ' . $e->getMessage(), [
                'request' => $request->all(),
                'exception' => $e->getTraceAsString()
            ]);
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to update society unit: ' . $e->getMessage(),
                'error_code' => $e->getCode()
            ], 500);
        }
    }

    public function destroy($id)
    {
        $unit = SocUnit::find($id);
        if (!$unit) {
            return response()->json([
                'status' => 'error',
                'message' => 'Society unit not found'
            ], 404);
        }

        try {
            $unit->delete();
            return response()->json([
                'status' => 'success',
                'message' => 'Society unit deleted successfully'
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error deleting society unit: ' . $e->getMessage(), [
                'id' => $id,
                'exception' => $e->getTraceAsString()
            ]);
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to delete society unit: ' . $e->getMessage(),
                'error_code' => $e->getCode()
            ], 500);
        }
    }
}
