<?php

namespace App\Http\Controllers;

use App\Helpers\IdentityValidator;
use App\Models\Ajustador;
use App\Models\Broker;
use App\Models\Caso;
use App\Models\Cliente;
use App\Models\EstadoHistorico;
use App\Models\PersonalZurich;
use App\Models\ProveedorEjecutivo;
use App\Models\Taller;
use App\Models\Tenant;
use App\Models\Vehiculo;
use App\Services\NotificationService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Inertia\Inertia;

class CasoController extends Controller
{
    public function index(Request $request)
    {
        $query = Caso::with(['cliente', 'vehiculo', 'aseguradora', 'broker', 'taller', 'ajustador']);

        if ($request->search) {
            $query->where(function ($q) use ($request) {
                $q->where('numero_reclamo', 'like', "%{$request->search}%")
                    ->orWhereHas('vehiculo', fn ($v) => $v->where('placa', 'like', "%{$request->search}%"))
                    ->orWhereHas('cliente', fn ($c) => $c->where('nombre', 'like', "%{$request->search}%"));
            });
        }

        if ($request->estado) {
            $query->where('estado_actual', $request->estado);
        }

        if ($request->aseguradora) {
            $query->where('aseguradora_id', $request->aseguradora);
        }

        $casos = $query->orderBy('created_at', 'desc')->paginate(20);
        $estados = Caso::ESTADOS;
        $aseguradoras = Tenant::orderBy('nombre')->get();

        return inertia('Casos/Index', [
            'title' => 'Casos',
            'casos' => $casos,
            'estados' => $estados,
            'aseguradoras' => $aseguradoras,
            'filtros' => $request->only(['search', 'estado', 'aseguradora']),
        ]);
    }

    public function create()
    {
        $aseguradoras = Tenant::orderBy('nombre')->get();
        $brokers = Broker::orderBy('razon_social')->get();
        $ajustadores = Ajustador::orderBy('nombre')->get();
        $talleres = Taller::orderBy('razon_social')->get();
        $ejecutivos = PersonalZurich::where('rol', 'ejecutivo')->orderBy('nombre')->get();
        $proveedorEjecutivos = ProveedorEjecutivo::orderBy('nombre')->get();

        return inertia('Casos/Create', [
            'title' => 'Nuevo Caso',
            'aseguradoras' => $aseguradoras,
            'brokers' => $brokers,
            'ajustadores' => $ajustadores,
            'talleres' => $talleres,
            'ejecutivos' => $ejecutivos,
            'proveedor_ejecutivos' => $proveedorEjecutivos,
            'estados' => Caso::ESTADOS,
        ]);
    }

    public function store(Request $request)
    {
        // dd($request->all()); // Debugging file upload
        $request->validate([
            'fecha_siniestro' => 'required|date',
            'cobertura' => 'required|in:DP,RC',
            'tipo_contrato' => 'required|in:E,P,X',
            'cliente.nombre' => 'required|string',
            'cliente.tipo_identificacion' => 'required|in:C,R,E',
            'cliente.ruc' => 'required|string',
            'vehiculo.placa' => 'required|string',
            'aviso_siniestro' => 'nullable|array',
            'aviso_siniestro.*' => 'file|mimes:pdf,jpg,png|max:10240', // Max 10MB
            'descripciones' => 'nullable|array',
            'descripciones.*' => 'nullable|string|max:500',
            'pago_estado' => 'required|in:pendiente,pagado,no_registra',
        ]);

        // PPTX Gap #1: Validate identity length by type
        $tipoId = $request->cliente['tipo_identificacion'];
        $numId = $request->cliente['ruc'];
        if ($tipoId === 'C' && strlen($numId) !== 10) {
            return back()->withErrors(['cliente.ruc' => 'La cédula debe tener exactamente 10 caracteres.'])->withInput();
        }
        if ($tipoId === 'R' && strlen($numId) !== 13) {
            return back()->withErrors(['cliente.ruc' => 'El RUC debe tener exactamente 13 caracteres.'])->withInput();
        }

        // Validar Identificación Ecuatoriana (CU02)
        if ($tipoId !== 'E' && ! IdentityValidator::validate($numId)) {
            return back()->withErrors(['cliente.ruc' => 'Identificación (Cédula/RUC) inválida para el formato ecuatoriano.'])->withInput();
        }

        // Crear cliente
        $cliente = Cliente::create([
            'tenant_id' => $request->aseguradora_id ?? 1, // Default tenant if P
            'nombre' => $request->cliente['nombre'],
            'telefono' => $request->cliente['telefono'] ?? null,
            'email' => $request->cliente['email'] ?? null,
            'tipo_identificacion' => $request->cliente['tipo_identificacion'],
            'ruc' => $request->cliente['ruc'],
            'ciudad' => $request->cliente['ciudad'] ?? null,
        ]);

        // Crear vehículo
        $vehiculo = Vehiculo::create([
            'tenant_id' => $request->aseguradora_id ?? 1,
            'placa' => $request->vehiculo['placa'],
            'marca' => $request->vehiculo['marca'] ?? null,
            'modelo' => $request->vehiculo['modelo'] ?? null,
            'anio' => $request->vehiculo['anio'] ?? null,
            'color' => $request->vehiculo['color'] ?? null,
            'tipo' => $request->vehiculo['tipo'] ?? 'liviano',
            'valor_asegurado' => $request->vehiculo['valor_asegurado'] ?? null,
            'has_extras' => $request->vehiculo['has_extras'] ?? false,
            'extras' => $request->vehiculo['extras'] ?? null,
        ]);

        // Handle file upload
        $avisoPaths = [];
        if ($request->hasFile('aviso_siniestro')) {
            foreach ($request->file('aviso_siniestro') as $i => $file) {
                $avisoPaths[] = [
                    'path' => $file->store('avisos', 'public'),
                    'nombre' => $file->getClientOriginalName(),
                    'descripcion' => ($request->input('descripciones')[$i] ?? '') ?: '',
                    'uploaded_by' => 'admin',
                    'uploaded_at' => now()->toDateTimeString(),
                ];
            }
        }

        // Crear caso
        $caso = Caso::create([
            'tenant_id' => $request->aseguradora_id ?? 1,
            'numero_reclamo' => $request->numero_reclamo ?: 'REC-'.strtoupper(Str::random(8)),
            'ramo' => $request->ramo ?? 'VH 07',
            'numero_caso_sias' => $request->numero_caso_sias ?? null,
            'numero_caso_wan_ax' => $request->numero_caso_wan_ax ?? null,
            'fecha_siniestro' => $request->fecha_siniestro,
            'cobertura' => $request->cobertura,
            'tipo_contrato' => $request->tipo_contrato,

            // Datos Aseguradora (E)
            'aseguradora_id' => $request->aseguradora_id ?: null,
            'aseguradora_razon_social' => $request->aseguradora_razon_social ?? null,
            'aseguradora_ruc' => $request->aseguradora_ruc ?? null,
            'aseguradora_ciudad' => $request->aseguradora_ciudad ?? null,
            'aseguradora_ejecutivo_nombre' => $request->aseguradora_ejecutivo_nombre ?? null,

            // Datos Broker
            'broker_id' => $request->broker_id ?? null,
            'broker_razon_social' => $request->broker_razon_social ?? null,
            'broker_ruc' => $request->broker_ruc ?? null,
            'broker_email' => $request->broker_email ?? null,
            'broker_telefono' => $request->broker_telefono ?? null,
            'broker_ejecutivo' => $request->broker_ejecutivo ?? null,
            'broker_nro_reclamo' => $request->broker_nro_reclamo ?? null,
            'broker_fecha_siniestro' => $request->broker_fecha_siniestro ?? null,

            // Datos Taller
            'taller_id' => $request->taller_id ?? null,
            'taller_ruc' => $request->taller_ruc ?? null,
            'taller_ejecutivo' => $request->taller_ejecutivo ?? null,
            'taller_email' => $request->taller_email ?? null,
            'taller_telefono' => $request->taller_telefono ?? null,

            // Datos Particular (P)
            'particular_nombre' => $request->particular_nombre ?? null,
            'particular_email' => $request->particular_email ?? null,
            'particular_telefono' => $request->particular_telefono ?? null,
            'particular_identificacion' => $request->particular_identificacion ?? null,
            'particular_tipo_identificacion' => $request->particular_tipo_identificacion ?? null,
            'particular_ciudad' => $request->particular_ciudad ?? null,

            // Afectado
            'afectado_nombre' => $request->afectado_nombre ?? null,
            'afectado_email' => $request->afectado_email ?? null,
            'afectado_telefono' => $request->afectado_telefono ?? null,

            'estado_actual' => 'pendiente_coordinacion',
            'observaciones' => $request->observaciones ?? null,
            'categoria_documento' => $request->categoria_documento ?? null,
            'tipo_ajuste' => $request->tipo_ajuste ?? null,
            'tipo_ajuste_carga' => $request->tipo_ajuste_carga ?? null,
            'aplica_kilometraje' => $request->aplica_kilometraje ?? false,
            'ciudad_destino' => $request->ciudad_destino ?? null,
            'kilometros' => $request->kilometros ?? 0,
            'tarifa_kilometro' => $request->tarifa_kilometro ?? 0,
            'valor_kilometraje' => $request->kilometros * $request->tarifa_kilometro,
            'tarifa_ajuste' => $request->tarifa_ajuste ?? 0,

            'ejecutivo_id' => $request->ejecutivo_id ?? null,
            'ejecutivo_email' => $request->ejecutivo_email ?? null,
            'ejecutivo_celular' => $request->ejecutivo_celular ?? null,
            'aviso_siniestro_path' => $avisoPaths,
            'director_id' => $request->director_id ?? null,
            'reinspector_id' => $request->reinspector_id ?? null,
            'cliente_id' => $cliente->id,
            'vehiculo_id' => $vehiculo->id,
            'fecha_asignacion' => $request->fecha_asignacion ?? now(),
            'fecha_inspeccion' => $request->fecha_inspeccion ?? null,
            'pago_estado' => $request->pago_estado ?? 'pendiente',
            'honorario_perito' => $request->honorario_perito ?? 0,
            'tarifa_ajustador_valor' => $request->tarifa_ajustador_valor ?? 0,
        ]);

        // Registrar en historial
        EstadoHistorico::create([
            'caso_id' => $caso->id,
            'estado' => 'pendiente_coordinacion',
            'fecha_ingreso' => now(),
        ]);

        // Notificar creación
        NotificationService::notify($caso, 'caso_creado', "Nuevo caso {$caso->numero_reclamo} registrado y pendiente de coordinación.");

        return redirect()->route('casos.index')->with('message', 'Caso creado exitosamente');
    }

    public function show(Caso $caso)
    {
        $caso->load(['cliente', 'vehiculo', 'aseguradora', 'broker', 'taller', 'ajustador', 'ejecutivo', 'estadosHistoricos']);

        // Normalizar aviso_siniestro_path a array
        $paths = $caso->aviso_siniestro_path;
        if (is_string($paths)) {
            $decoded = json_decode($paths, true);
            $caso->aviso_siniestro_path = is_array($decoded) ? $decoded : [];
        } elseif (! is_array($paths)) {
            $caso->aviso_siniestro_path = [];
        }

        // Normalizar ajustador_archivos a array
        $ajustadorPaths = $caso->ajustador_archivos;
        if (is_string($ajustadorPaths)) {
            $decoded = json_decode($ajustadorPaths, true);
            $caso->ajustador_archivos = is_array($decoded) ? $decoded : [];
        } elseif (! is_array($ajustadorPaths)) {
            $caso->ajustador_archivos = [];
        }

        return inertia('Casos/Show', [
            'title' => 'Caso '.$caso->numero_reclamo,
            'caso' => $caso,
            'estados' => Caso::ESTADOS,
        ]);
    }

    public function edit(Caso $caso)
    {
        $caso->load(['cliente', 'vehiculo']);

        // Normalizar aviso_siniestro_path a array
        $paths = $caso->aviso_siniestro_path;
        if (is_string($paths)) {
            $decoded = json_decode($paths, true);
            $caso->aviso_siniestro_path = is_array($decoded) ? $decoded : [];
        } elseif (! is_array($paths)) {
            $caso->aviso_siniestro_path = [];
        }

        // Normalizar ajustador_archivos a array
        $archivos = $caso->ajustador_archivos;
        if (is_string($archivos)) {
            $decoded = json_decode($archivos, true);
            $caso->ajustador_archivos = is_array($decoded) ? $decoded : [];
        } elseif (! is_array($archivos)) {
            $caso->ajustador_archivos = [];
        }

        $aseguradoras = Tenant::orderBy('nombre')->get();
        $brokers = Broker::orderBy('razon_social')->get();
        $ajustadores = Ajustador::orderBy('nombre')->get();
        $talleres = Taller::orderBy('razon_social')->get();
        $ejecutivos = PersonalZurich::where('rol', 'ejecutivo')->orderBy('nombre')->get();
        $proveedorEjecutivos = ProveedorEjecutivo::orderBy('nombre')->get();

        return inertia('Casos/Edit', [
            'title' => 'Editar Caso',
            'caso' => $caso,
            'aseguradoras' => $aseguradoras,
            'brokers' => $brokers,
            'ajustadores' => $ajustadores,
            'talleres' => $talleres,
            'ejecutivos' => $ejecutivos,
            'proveedor_ejecutivos' => $proveedorEjecutivos,
            'estados' => Caso::ESTADOS,
        ]);
    }

    public function update(Request $request, Caso $caso)
    {
        $request->validate([
            'fecha_siniestro' => 'required|date',
            'cobertura' => 'required|in:DP,RC',
            'aviso_siniestro' => 'nullable|array',
            'aviso_siniestro.*' => 'file|mimes:pdf,jpg,png|max:10240',
            'descripciones' => 'nullable|array',
            'descripciones.*' => 'nullable|string|max:500',
            'archivos_a_eliminar' => 'nullable|array',
        ]);

        $caso->update($request->only([
            'fecha_siniestro',
            'cobertura',
            'tipo_contrato',
            'numero_caso_sias',
            'numero_caso_wan_ax',
            'observaciones',
            'categoria_documento',
            'tipo_ajuste',
            'tipo_ajuste_carga',
            'aplica_kilometraje',
            'ciudad_destino',
            'kilometros',
            'tarifa_kilometro',
            'valor_kilometraje',
            'tarifa_ajuste',
            'afectado_nombre',
            'afectado_email',
            'afectado_telefono',
            'aseguradora_id',
            'broker_id',
            'ajustador_id',
            'taller_id',
            'taller_ruc',
            'taller_ejecutivo',
            'taller_email',
            'taller_telefono',
            'ejecutivo_id',
            'broker_ejecutivo',
            'pago_estado',
            'estado_coordinacion',
            'fecha_asignacion',
            'fecha_inspeccion',
            'honorario_perito',
        ]));

        // Actualizar cliente y vehículo
        if ($request->cliente) {
            $caso->cliente->update($request->cliente);
        }
        if ($request->vehiculo) {
            $caso->vehiculo->update($request->vehiculo);
        }

        // Filtrar archivos marcados para eliminar
        $existingPaths = is_array($caso->aviso_siniestro_path) ? $caso->aviso_siniestro_path : [];
        if ($request->has('archivos_a_eliminar')) {
            $toDelete = $request->archivos_a_eliminar;
            $existingPaths = array_values(array_filter($existingPaths, function ($item) use ($toDelete) {
                $itemPath = is_string($item) ? $item : ($item['path'] ?? null);

                return ! in_array($itemPath, $toDelete) && ! in_array($item, $toDelete, true);
            }));
        }

        // Subir nuevos archivos
        $newPaths = [];
        if ($request->hasFile('aviso_siniestro')) {
            foreach ($request->file('aviso_siniestro') as $i => $file) {
                $newPaths[] = [
                    'path' => $file->store('avisos', 'public'),
                    'nombre' => $file->getClientOriginalName(),
                    'descripcion' => ($request->input('descripciones')[$i] ?? '') ?: '',
                    'uploaded_by' => 'admin',
                    'uploaded_at' => now()->toDateTimeString(),
                ];
            }
        }

        // Combinar existentes filtrados + nuevos y actualizar
        $caso->update([
            'aviso_siniestro_path' => array_merge($existingPaths, $newPaths),
        ]);

        return redirect()->route('casos.show', $caso->id)->with('message', 'Caso actualizado');
    }

    public function cambiarEstado(Request $request, Caso $caso)
    {
        $request->validate([
            'estado' => 'required|string',
            'nota' => 'nullable|string',
        ]);

        $newEstado = $request->estado;

        // Cerrar el estado anterior en el historial
        $ultimoHistorico = $caso->estadosHistoricos()->orderBy('created_at', 'desc')->first();
        if ($ultimoHistorico) {
            $fechaSalida = now();
            $duracion = $ultimoHistorico->created_at->diffInMinutes($fechaSalida);

            $ultimoHistorico->update([
                'fecha_salida' => $fechaSalida,
                'duracion_minutas' => $duracion,
            ]);
        }

        $caso->update([
            'estado_actual' => $newEstado,
            'fecha_cierre' => $newEstado === 'finalizado' ? now() : null,
        ]);

        // Registrar en el historial
        $caso->estadosHistoricos()->create([
            'estado' => $newEstado,
            'nota' => $request->nota,
            'usuario_id' => auth()->id(),
            'fecha_ingreso' => now(),
        ]);

        // Notificar cambio de estado
        NotificationService::notify($caso, 'estado_actualizado', "Estado actualizado a '{$newEstado}'".($request->nota ? ": {$request->nota}" : ''));

        return back()->with('message', 'Estado actualizado correctamente');
    }

    public function deleteFile(Request $request, Caso $caso, int $index)
    {
        $tipo = $request->tipo ?? 'admin';

        if ($tipo === 'admin') {
            $archivos = $this->normalizarArchivos($caso->aviso_siniestro_path);
            if (isset($archivos[$index])) {
                unset($archivos[$index]);
                $caso->update(['aviso_siniestro_path' => array_values($archivos)]);
            }
        } else {
            $archivos = $this->normalizarArchivos($caso->ajustador_archivos);
            if (isset($archivos[$index])) {
                unset($archivos[$index]);
                $caso->update(['ajustador_archivos' => array_values($archivos)]);
            }
        }

        return back()->with('message', 'Archivo eliminado correctamente');
    }

    private function normalizarArchivos($valor): array
    {
        if (is_array($valor)) {
            return $valor;
        }
        if (is_string($valor)) {
            $decoded = json_decode($valor, true);

            return is_array($decoded) ? $decoded : [];
        }

        return [];
    }

    public function destroy(Caso $caso)
    {
        // Eliminar registros relacionados primero
        // Estados históricos
        $caso->estadosHistoricos()->delete();

        // Notificaciones
        $caso->notificaciones()->delete();

        // Cotizaciones y sus items
        foreach ($caso->cotizaciones as $cotizacion) {
            $cotizacion->items()->delete();
        }
        $caso->cotizaciones()->delete();

        // Facturas y sus items
        foreach ($caso->facturas as $factura) {
            $factura->items()->delete();
        }
        $caso->facturas()->delete();

        // Seguimiento de reparación
        $caso->seguimientoReparacion()->delete();

        // Guardar referencias para eliminar después
        $clienteId = $caso->cliente_id;
        $vehiculoId = $caso->vehiculo_id;

        // Eliminar el caso
        $caso->delete();

        // Eliminar cliente y vehículo (solo si no están relacionados con otros casos)
        if ($clienteId) {
            $clienteUsado = Caso::where('cliente_id', $clienteId)->count();
            if ($clienteUsado === 0) {
                Cliente::find($clienteId)?->delete();
            }
        }

        if ($vehiculoId) {
            $vehiculoUsado = Caso::where('vehiculo_id', $vehiculoId)->count();
            if ($vehiculoUsado === 0) {
                Vehiculo::find($vehiculoId)?->delete();
            }
        }

        return redirect()->route('casos.index')->with('message', 'Caso eliminado correctamente');
    }

    public function estadosIndex(Request $request)
    {
        $query = Caso::with(['aseguradora', 'cliente', 'vehiculo']);

        if ($request->search) {
            $query->whereHas('vehiculo', function ($q) use ($request) {
                $q->where('placa', 'like', '%'.$request->search.'%');
            })->orWhere('numero_reclamo', 'like', '%'.$request->search.'%');
        }

        $casos = $query->orderBy('updated_at', 'desc')->get();

        return Inertia::render('Estados/Index', [
            'title' => 'Gestión de Estados',
            'casos' => $casos,
            'filters' => $request->only(['search']),
        ]);
    }

    public function timelineIndex(Request $request)
    {
        $query = Caso::with(['aseguradora', 'cliente', 'vehiculo']);

        if ($request->search) {
            $query->whereHas('vehiculo', function ($q) use ($request) {
                $q->where('placa', 'like', '%'.$request->search.'%');
            })->orWhere('numero_reclamo', 'like', '%'.$request->search.'%');
        }

        $casos = $query->orderBy('updated_at', 'desc')->get();

        return Inertia::render('Timeline/Index', [
            'title' => 'Línea de Tiempo Integral',
            'casos' => $casos,
            'filters' => $request->only(['search']),
        ]);
    }

    public function estados(Caso $caso)
    {
        $caso->load(['aseguradora', 'cliente', 'vehiculo', 'estadosHistoricos.user']);

        return Inertia::render('Estados/Show', [
            'title' => 'Gestión de Estados - Caso '.($caso->numero_reclamo ?? $caso->id),
            'caso' => $caso,
            'estados' => Caso::ESTADOS,
        ]);
    }

    public function updateEstado(Request $request, Caso $caso)
    {
        $request->validate([
            'estado_actual' => 'required|string',
            'nota' => 'nullable|string|max:1000',
            'sub_estado_taller' => 'nullable|string',
        ]);

        $oldEstado = $caso->estado_actual;
        $newEstado = $request->estado_actual;

        // Cerrar el estado anterior en el historial
        $ultimoHistorico = $caso->estadosHistoricos()->orderBy('created_at', 'desc')->first();
        if ($ultimoHistorico) {
            $fechaSalida = now();
            $duracion = $ultimoHistorico->created_at->diffInMinutes($fechaSalida);

            $ultimoHistorico->update([
                'fecha_salida' => $fechaSalida,
                'duracion_minutas' => $duracion,
            ]);
        }

        $caso->update([
            'estado_actual' => $newEstado,
            'sub_estado_taller' => $request->sub_estado_taller,
        ]);

        // Registrar en el historial
        $caso->estadosHistoricos()->create([
            'estado' => $newEstado,
            'nota' => $request->nota,
            'sub_estado_taller' => $request->sub_estado_taller,
            'usuario_id' => auth()->id(),
            'fecha_ingreso' => now(),
        ]);

        return redirect()->back()->with('message', 'Estado actualizado correctamente');
    }
}
