<?php

namespace App\Http\Controllers;

use App\Models\AccessLog;
use App\Models\Visitor;
use App\Models\Vehicle;
use App\Models\Zone;
use App\Models\AccessPoint;
use App\Models\ParkingSpace;
use App\Models\ParkingAssignment;
use App\Models\Delivery;
use App\Models\DeliveryQrLog;
use App\Models\IdentityCheck;
use App\Enums\AccessType;
use App\Enums\AccessStatus;
use App\Services\RegistroCivilService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class AccessController extends Controller
{
    protected $registroCivilService;

    public function __construct(RegistroCivilService $registroCivilService)
    {
        $this->registroCivilService = $registroCivilService;
    }

    public function index(Request $request)
    {
        $user = Auth::user();
        $query = AccessLog::with(['visitor', 'vehicle', 'zone', 'guardUser', 'parkingAssignment.parkingSpace']);

        if ($user->account_id) {
            $query->where('account_id', $user->account_id);
        }

        // Filtros
        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        if ($request->filled('date')) {
            $query->whereDate('entered_at', $request->date);
        } else {
            $query->whereDate('entered_at', today());
        }

        $logs = $query->orderBy('entered_at', 'desc')->paginate(15);

        return view('access.index', compact('logs'));
    }

    public function create()
    {
        $user = Auth::user();
        $accountId = $user->account_id;

        // Cargar zonas, puntos de acceso y estacionamientos del recinto del usuario
        $zones = Zone::where('account_id', $accountId)->get();
        $accessPoints = AccessPoint::where('account_id', $accountId)->get();
        $parkingSpaces = ParkingSpace::where('account_id', $accountId)->where('is_occupied', false)->get();

        // Si no existen zonas o puntos creados aún (primer login), creamos registros por defecto
        if ($zones->isEmpty() && $accountId) {
            $zones = collect([
                Zone::create(['account_id' => $accountId, 'name' => 'Oficina 3B']),
                Zone::create(['account_id' => $accountId, 'name' => 'Recepción']),
                Zone::create(['account_id' => $accountId, 'name' => 'Departamento 12B']),
                Zone::create(['account_id' => $accountId, 'name' => 'Bodega Norte']),
            ]);
        }

        if ($accessPoints->isEmpty() && $accountId) {
            $accessPoints = collect([
                AccessPoint::create(['account_id' => $accountId, 'name' => 'Entrada Principal']),
                AccessPoint::create(['account_id' => $accountId, 'name' => 'Acceso Vehicular']),
            ]);
        }

        if ($parkingSpaces->isEmpty() && $accountId) {
            // Crear 10 estacionamientos de prueba
            for ($i = 1; $i <= 10; $i++) {
                ParkingSpace::create([
                    'account_id' => $accountId,
                    'number' => 'Estacionamiento ' . $i,
                    'type' => 'visitor',
                    'is_occupied' => false
                ]);
            }
            $parkingSpaces = ParkingSpace::where('account_id', $accountId)->where('is_occupied', false)->get();
        }

        return view('access.create', compact('zones', 'accessPoints', 'parkingSpaces'));
    }

    /**
     * AJAX endpoint to query Registro Civil
     */
    public function verifyIdentity(Request $request)
    {
        $request->validate(['rut' => 'required|string']);
        
        $data = $this->registroCivilService->verifyIdentity($request->rut);
        
        if (!$data) {
            return response()->json(['success' => false, 'message' => 'RUT inválido o formato incorrecto.'], 422);
        }

        return response()->json($data);
    }

    public function store(Request $request)
    {
        $request->validate([
            'access_type' => 'required|in:person,vehicle,delivery',
            'rut' => 'required|string',
            'first_name' => 'required|string',
            'last_name' => 'required|string',
            'birth_date' => 'nullable|date',
            'nationality' => 'required|string',
            'zone_id' => 'required|exists:zones,id',
            'access_point_id' => 'required|exists:access_points,id',
            'accompanied_by' => 'nullable|string',
            'observations' => 'nullable|string|max:255',
            
            // Vehículo
            'plate' => 'required_if:access_type,vehicle|nullable|string',
            'vehicle_type' => 'nullable|string',
            'parking_space_id' => 'required_if:access_type,vehicle|nullable|exists:parking_spaces,id',
            
            // Delivery
            'delivery_company' => 'required_if:access_type,delivery|nullable|string',
            'delivery_recipient' => 'nullable|string',
            'delivery_point' => 'required_if:access_type,delivery|nullable|string',
            'qr_url' => 'nullable|string',
        ]);

        $user = Auth::user();

        DB::beginTransaction();

        try {
            // 1. Guardar o actualizar Visitante
            $visitor = Visitor::updateOrCreate(
                ['rut' => $request->rut],
                [
                    'first_name' => $request->first_name,
                    'last_name' => $request->last_name,
                    'birth_date' => $request->birth_date,
                    'nationality' => $request->nationality,
                ]
            );

            // Registro Civil Check Log
            IdentityCheck::create([
                'visitor_id' => $visitor->id,
                'rut_queried' => $request->rut,
                'is_valid' => true,
                'api_provider' => 'registro_civil_mock',
                'raw_response' => [
                    'verified_at' => now()->toDateTimeString(),
                    'visitor_id' => $visitor->id
                ]
            ]);

            // 2. Si es Vehicular, guardar o asociar Vehículo
            $vehicleId = null;
            if ($request->access_type === 'vehicle') {
                $vehicle = Vehicle::updateOrCreate(
                    ['plate' => strtoupper($request->plate)],
                    ['type' => $request->vehicle_type]
                );
                $vehicleId = $vehicle->id;
            }

            // 3. Crear Access Log
            $log = AccessLog::create([
                'account_id' => $user->account_id,
                'visitor_id' => $visitor->id,
                'vehicle_id' => $vehicleId,
                'zone_id' => $request->zone_id,
                'access_point_id' => $request->access_point_id,
                'guard_id' => $user->id,
                'type' => AccessType::from($request->access_type),
                'status' => AccessStatus::AUTHORIZED,
                'entered_at' => now(),
                'observations' => $request->observations,
                'accompanied_by' => $request->accompanied_by,
            ]);

            // 4. Si es Vehicular, asignar estacionamiento y marcar como ocupado
            if ($request->access_type === 'vehicle') {
                ParkingAssignment::create([
                    'access_log_id' => $log->id,
                    'parking_space_id' => $request->parking_space_id,
                    'assigned_at' => now(),
                ]);

                $space = ParkingSpace::find($request->parking_space_id);
                $space->update(['is_occupied' => true]);
            }

            // 5. Si es Delivery, registrar entrega y QR
            if ($request->access_type === 'delivery') {
                $delivery = Delivery::create([
                    'access_log_id' => $log->id,
                    'company' => $request->delivery_company,
                    'recipient_name' => $request->delivery_recipient,
                    'delivery_point' => $request->delivery_point,
                ]);

                if ($request->qr_url) {
                    DeliveryQrLog::create([
                        'delivery_id' => $delivery->id,
                        'qr_content_url' => $request->qr_url,
                    ]);
                }
            }

            DB::commit();

            return redirect()->route('dashboard')->with('success', 'Ingreso registrado exitosamente.');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->withInput()->with('error', 'Error al registrar el acceso: ' . $e->getMessage());
        }
    }

    public function exit($id)
    {
        DB::beginTransaction();

        try {
            $log = AccessLog::findOrFail($id);
            $log->update(['exited_at' => now()]);

            // Si tiene estacionamiento asignado, liberarlo
            if ($log->type === AccessType::VEHICLE && $log->parkingAssignment) {
                $assignment = $log->parkingAssignment;
                $assignment->update(['released_at' => now()]);
                
                $space = $assignment->parkingSpace;
                $space->update(['is_occupied' => false]);
            }

            DB::commit();
            return redirect()->back()->with('success', 'Salida registrada con éxito.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Error al registrar la salida: ' . $e->getMessage());
        }
    }
}
