arcos-backend/app/Services/VehicleService.php

250 lines
7.9 KiB
PHP

<?php
namespace App\Services;
use App\Models\Vehicle;
use App\Models\Detection;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
class VehicleService
{
public function __construct(
private ConsultaEstatalService $consultaEstatal,
private ReporteRoboService $reporteRobo,
private ConsultaRepuveConstancia $consultaRepuveCons
) {}
public function procesarDeteccion(string $epc, ?int $arcoId = null): array
{
$key = "vehiculo:robado:{$epc}";
// Verificar si está en Redis
$enRedis = Redis::get($key);
if ($enRedis) {
// Ya está marcado como robado, verificar si sigue así
$resultado = $this->verificarVehiculoRobado($epc, $arcoId, json_decode($enRedis, true));
$this->registrarDeteccion($epc, $resultado);
return $resultado;
}
// No está en Redis, consultar servicios
$resultado = $this->consultarNuevoVehiculo($epc, $arcoId);
$this->registrarDeteccion($epc, $resultado);
return $resultado;
}
private function consultarNuevoVehiculo(string $epc, ?int $arcoId): array
{
// Consultar padrón estatal
$datosEstatal = $this->consultaEstatal->consultarPorEpc($epc);
if (!$datosEstatal || !$datosEstatal['vin']) {
return [
'success' => false,
'message' => 'No se encontró información del vehículo'
];
}
// Consultar REPUVE
$reporteRobo = $this->reporteRobo->consultarPorVin(
$datosEstatal['vin'],
$datosEstatal['placa']
);
if ($reporteRobo['tiene_reporte']) {
// Está robado → Guardar en Redis
$this->guardarEnRedis($epc, $datosEstatal, $reporteRobo['datos']);
Log::warning('¡VEHÍCULO ROBADO DETECTADO!', [
'epc' => $epc,
'vin' => $datosEstatal['vin'],
'placa' => $datosEstatal['placa']
]);
return [
'success' => true,
'tiene_reporte_robo' => true,
'estado' => 'ROBADO',
'accion' => 'GUARDADO_EN_REDIS',
'vehiculo' => array_merge($datosEstatal, $reporteRobo['datos'])
];
}
// No está robado, no hacer nada
return [
'success' => true,
'tiene_reporte_robo' => false,
'estado' => 'LIBRE',
'vehiculo' => $datosEstatal
];
}
private function verificarVehiculoRobado(string $epc, ?int $arcoId, array $datosRedis): array
{
// Consultar REPUVE para verificar estado actual
$reporteRobo = $this->reporteRobo->consultarPorVin(
$datosRedis['vin'],
$datosRedis['placa']
);
if (!$reporteRobo['tiene_reporte']) {
// No tiene reporte robo
$this->registrarRecuperacion($epc, $arcoId, $datosRedis);
Log::info('¡VEHÍCULO RECUPERADO!', [
'epc' => $epc,
'vin' => $datosRedis['vin'],
'placa' => $datosRedis['placa']
]);
return [
'success' => true,
'tiene_reporte_robo' => false,
'estado' => 'RECUPERADO',
'accion' => 'GUARDADO_EN_MYSQL_Y_ELIMINADO_DE_REDIS',
'vehiculo' => $datosRedis
];
}
// Sigue robado → Actualizar contador en Redis
$this->actualizarDeteccionRedis($epc, $datosRedis);
Log::warning('Vehículo robado detectado nuevamente', [
'epc' => $epc,
'detecciones' => $datosRedis['detecciones'] + 1
]);
return [
'success' => true,
'tiene_reporte_robo' => true,
'estado' => 'ROBADO',
'accion' => 'ACTUALIZADO_EN_REDIS',
'vehiculo' => $datosRedis
];
}
private function guardarEnRedis(string $epc, array $datosEstatal, array $datosRobo)
{
$key = "vehiculo:robado:{$epc}";
$datos = [
'epc' => $epc,
'vin' => $datosEstatal['vin'],
'placa' => $datosEstatal['placa'],
'fecha_robo' => $datosRobo['fecha_robo'] ?? null,
'autoridad' => $datosRobo['autoridad'] ?? null,
'acta' => $datosRobo['acta'] ?? null,
'denunciante' => $datosRobo['denunciante'] ?? null,
'fecha_acta' => $datosRobo['fecha_acta'] ?? null,
'primera_deteccion' => now()->toIso8601String(),
'ultima_deteccion' => now()->toIso8601String(),
'detecciones' => 1
];
Redis::set($key, json_encode($datos));
}
private function actualizarDeteccionRedis(string $epc, array $datosActuales)
{
$key = "vehiculo:robado:{$epc}";
$datosActuales['ultima_deteccion'] = now()->toIso8601String();
$datosActuales['detecciones'] = ($datosActuales['detecciones'] ?? 0) + 1;
Redis::set($key, json_encode($datosActuales));
}
private function registrarRecuperacion(string $epc, ?int $arcoId, array $datosRedis)
{
// Guardar en MySQL
Vehicle::create([
'epc' => $epc,
'vin' => $datosRedis['vin'],
'placa' => $datosRedis['placa'],
'fecha_robo' => $datosRedis['fecha_robo'],
'autoridad_robo' => $datosRedis['autoridad'],
'acta_robo' => $datosRedis['acta'],
'denunciante' => $datosRedis['denunciante'],
'fecha_recuperacion' => now(),
'fecha_acta' => $datosRedis['fecha_acta'] ?? null,
'datos_robo_original' => $datosRedis
]);
// Eliminar de Redis
Redis::del("vehiculo:robado:{$epc}");
}
public function listarVehiculosRobados(): array
{
$keys = Redis::keys('vehiculo:robado:*');
$vehiculos = [];
foreach ($keys as $key) {
$datos = Redis::get($key);
if ($datos) {
$vehiculos[] = json_decode($datos, true);
}
}
return $vehiculos;
}
private function registrarDeteccion(string $epc, array $resultado)
{
if (!$resultado['success'] || !isset($resultado['vehiculo'])) {
return;
}
$vehiculo = $resultado['vehiculo'];
Detection::create([
'epc' => $epc,
'vin' => $vehiculo['vin'] ?? null,
'placa' => $vehiculo['placa'] ?? null,
'marca' => $vehiculo['marca'] ?? null,
'modelo' => $vehiculo['modelo'] ?? null,
'color' => $vehiculo['color'] ?? null,
'fecha_deteccion' => now()
]);
}
/**
* Consultar vehículo por tag_id
*/
public function consultarVehiculoPorTag(?string $epc = null, ?string $tagId = null)
{
try {
// Validar que se proporcionó tag_id
if (empty($tagId)) {
Log::warning('VehicleService: No se proporcionó tag_id');
return null;
}
$vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($tagId);
if ($vehiculoExterno) {
Log::info('VehicleService: Vehículo encontrado', [
'tag_id' => $vehiculoExterno['tag_id'] ?? null,
'tag_number' => $vehiculoExterno['tag_number'] ?? null,
'vin' => $vehiculoExterno['vin'] ?? null
]);
} else {
Log::info('VehicleService: Vehículo no encontrado', [
'tag_id' => $tagId
]);
}
return $vehiculoExterno;
} catch (\Exception $e) {
Log::error('VehicleService: Error en consulta', [
'tag_id' => $tagId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return null;
}
}
}