<?php

namespace App\Http\Controllers;

use App\Models\NotificacionOperativa;
use App\Models\ReporteOperativo;
use App\Models\ReporteOperativoDetalle;
use App\Models\ReporteOperativoFuente;
use App\Models\Unidade;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;

class ReporteOperativoController extends Controller
{
    /*
|--------------------------------------------------------------------------
| ROL ACTUAL DEL USUARIO
|--------------------------------------------------------------------------
|
*/
    private function rolesUsuario($user): array
    {
        if (!$user || !$user->role_id) {
            return [];
        }

        $rolActual =
            DB::table('roles')
            ->where(
                'id',
                $user->role_id
            )
            ->value('name');

        return $rolActual
            ? [$rolActual]
            : [];
    }

    private function esRol(string ...$roles): bool
    {
        $rolesUsuario = $this->rolesUsuario(auth()->user());

        foreach ($roles as $rol) {
            if (in_array($rol, $rolesUsuario, true)) {
                return true;
            }
        }

        return false;
    }

    /*
    |--------------------------------------------------------------------------
    | UTILIDADES DE ESQUEMA
    |--------------------------------------------------------------------------
    */
    private function primeraColumnaExistente(string $tabla, array $candidatas): ?string
    {
        foreach ($candidatas as $columna) {
            if (Schema::hasColumn($tabla, $columna)) {
                return $columna;
            }
        }

        return null;
    }

    private function filtrarColumnasModelo($modelo, array $datos): array
    {
        $tabla = $modelo->getTable();
        $columnas = Schema::getColumnListing($tabla);

        return array_intersect_key(
            $datos,
            array_flip($columnas)
        );
    }

    /*
    |--------------------------------------------------------------------------
    | FECHA DEL REPORTE DIARIO
    |--------------------------------------------------------------------------
    */
    private function fechaReporteDiario(Request $request): array
    {
        $validator = Validator::make(
            $request->all(),
            [
                'fecha_reporte' => [
                    'required',
                    'date_format:Y-m-d',
                ],
            ],
            [
                'fecha_reporte.required' =>
                'Debe seleccionar la fecha del reporte.',
                'fecha_reporte.date_format' =>
                'La fecha del reporte no tiene un formato válido.',
            ]
        );

        if ($validator->fails()) {
            return [
                'ok' => false,
                'response' => response()->json(
                    [
                        'message' => 422,
                        'message_text' =>
                        'DEBE SELECCIONAR UNA FECHA VÁLIDA',
                        'errors' => $validator->errors(),
                    ],
                    422
                ),
            ];
        }

        $fecha = Carbon::createFromFormat(
            'Y-m-d',
            $request->fecha_reporte,
            config('app.timezone', 'America/La_Paz')
        )->format('Y-m-d');

        return [
            'ok' => true,
            'periodo_ini' => $fecha,
            'periodo_fin' => $fecha,
        ];
    }

    /*
    |--------------------------------------------------------------------------
    | CONTEXTO DEL P-3
    |--------------------------------------------------------------------------
    */
    private function contextoP3(): array
    {
        $user = auth()->user();

        if (!$user) {
            return [
                'ok' => false,
                'message' => 'USUARIO NO AUTENTICADO',
            ];
        }

        if (!$user->user_uni_cod) {
            return [
                'ok' => false,
                'message' =>
                'EL USUARIO P-3 NO TIENE UNA UNIDAD ASIGNADA',
            ];
        }

        $unidad = Unidade::where(
            'uni_cod',
            $user->user_uni_cod
        )->first();

        if (!$unidad) {
            return [
                'ok' => false,
                'message' => 'NO SE ENCONTRÓ LA UNIDAD DEL P-3',
            ];
        }

        $divisionCod = $unidad->uni_codsup ?? null;

        if (!$divisionCod) {
            return [
                'ok' => false,
                'message' =>
                'LA UNIDAD DEL P-3 NO TIENE UNA DIVISIÓN SUPERIOR CONFIGURADA',
            ];
        }

        $division = Unidade::where(
            'uni_cod',
            $divisionCod
        )->first();

        if (!$division) {
            return [
                'ok' => false,
                'message' => 'NO SE ENCONTRÓ LA DIVISIÓN DEL P-3',
            ];
        }

        return [
            'ok' => true,
            'user' => $user,
            'unidad' => $unidad,
            'division' => $division,
        ];
    }

    /*
|--------------------------------------------------------------------------
| BUSCAR P-3 VIGENTE DE UNA UNIDAD
|--------------------------------------------------------------------------
|
| Fuente oficial:
|
| users.role_id -> roles.id
| users.user_uni_cod -> Unidad asignada
|
*/
    private function buscarP3Unidad($unidadCod)
    {
        return User::query()

            ->select(
                'users.*'
            )

            ->join(
                'roles as r',
                'r.id',
                '=',
                'users.role_id'
            )

            ->where(
                'users.state',
                1
            )

            ->where(
                'users.user_uni_cod',
                $unidadCod
            )

            ->where(
                'r.name',
                'P-3'
            )

            ->orderBy(
                'users.id'
            )

            ->get();
    }

    /*
|--------------------------------------------------------------------------
| BUSCAR G-3 VIGENTE DE LA DIVISIÓN
|--------------------------------------------------------------------------
|
*/
    private function buscarG3Division($divisionCod)
    {
        return User::query()

            ->select(
                'users.*'
            )

            ->join(
                'roles as r',
                'r.id',
                '=',
                'users.role_id'
            )

            ->where(
                'users.state',
                1
            )

            ->where(
                'users.user_uni_cod',
                $divisionCod
            )

            ->where(
                'r.name',
                'G-3'
            )

            ->orderBy(
                'users.id'
            )

            ->get();
    }

    /*
    |--------------------------------------------------------------------------
    | BUSCAR ADMINISTRADOR DEL DPTO. III
    |--------------------------------------------------------------------------
    */
    private function buscarAdministradorDptoIII(): ?User
    {
        return User::query()
            ->whereHas(
                'roles',
                function ($query) {
                    $query->where('name', 'Admin-Dpto-III');
                }
            )
            ->orderBy('id')
            ->first();
    }

    /*
    |--------------------------------------------------------------------------
    | CREAR NOTIFICACIÓN OPERATIVA
    |--------------------------------------------------------------------------
    */
    private function crearNotificacion(array $datos): NotificacionOperativa
    {
        $modelo = new NotificacionOperativa();

        $payload = array_merge(
            [
                'notif_estado' => 'NUEVA',
                'notif_prioridad' => 'NORMAL',
                'notif_activo' => 'A',
                'notif_fechareg' => now(),
            ],
            $datos
        );

        $modelo->forceFill(
            $this->filtrarColumnasModelo(
                $modelo,
                $payload
            )
        );

        $modelo->save();

        return $modelo;
    }

    private function marcarNotificacionesLeidas(
        int $reporteId,
        int $usuarioId,
        ?array $tipos = null
    ): void {
        $query = NotificacionOperativa::where(
            'notif_repop_cod',
            $reporteId
        )
            ->where(
                'notif_user_destino',
                $usuarioId
            )
            ->where(
                'notif_estado',
                'NUEVA'
            )
            ->where(
                'notif_activo',
                'A'
            );

        if ($tipos && count($tipos)) {
            $query->whereIn('notif_tipo', $tipos);
        }

        $query->update(
            [
                'notif_estado' => 'LEIDA',
                'notif_fecha_lectura' => now(),
                'notif_usuamod' => $usuarioId,
                'notif_fechamod' => now(),
            ]
        );
    }

    /*
    |--------------------------------------------------------------------------
    | DETALLE VIVO DE UNA UNIDAD
    |--------------------------------------------------------------------------
    |
    | Obtiene las misiones activas y el personal asignado a la unidad para la
    | fecha seleccionada. Se evita depender de columnas opcionales de PERSONAS.
    |
    */
    private function detalleUnidad(
        $unidadCod,
        $divisionCod,
        string $periodoIni,
        string $periodoFin
    ) {
        $unidad = Unidade::where(
            'uni_cod',
            $unidadCod
        )->first();

        $division = Unidade::where(
            'uni_cod',
            $divisionCod
        )->first();

        $columnaCi = $this->primeraColumnaExistente(
            'personas',
            [
                'per_ci',
                'per_carnet',
                'per_nrodoc',
                'per_nro_doc',
            ]
        );

        $columnaIdentificacion = $this->primeraColumnaExistente(
            'personas',
            [
                'per_codigo_identificacion',
                'per_cod_identificacion',
                'per_codigo',
            ]
        );

        $ciSelect = $columnaCi
            ? DB::raw("p.{$columnaCi} AS ci")
            : DB::raw('NULL AS ci');

        $identificacionSelect = $columnaIdentificacion
            ? DB::raw("p.{$columnaIdentificacion} AS codigo_identificacion")
            : DB::raw('NULL AS codigo_identificacion');

        $query = DB::table('misiones as m')
            ->join(
                'misione_items as mi',
                'mi.mitem_mision_cod',
                '=',
                'm.mision_cod'
            )
            ->join(
                'users as us',
                'us.id',
                '=',
                'mi.mitem_user_id'
            )
            ->join(
                'personas as p',
                'p.per_cod',
                '=',
                'us.user_per_cod'
            )
            ->leftJoin(
                'puestos as pu',
                'pu.puesto_cod',
                '=',
                'm.mision_puesto_cod'
            )
            ->leftJoin(
                'persona_grados as pg',
                function ($join) {
                    $join
                        ->on(
                            'pg.pergrad_per_cod',
                            '=',
                            'p.per_cod'
                        )
                        ->where(
                            'pg.pergrad_estado',
                            'A'
                        );
                }
            )
            ->leftJoin(
                'grados as g',
                'g.grad_cod',
                '=',
                'pg.pergrad_grad_cod'
            )
            ->leftJoin(
                'persona_especialidades as pe',
                function ($join) {
                    $join
                        ->on(
                            'pe.perespe_per_cod',
                            '=',
                            'p.per_cod'
                        )
                        ->where(
                            'pe.perespe_estado',
                            'A'
                        );
                }
            )
            ->leftJoin(
                'especialidades as e',
                'e.espe_cod',
                '=',
                'pe.perespe_espe_cod'
            )
            ->where(
                'm.mision_uni_cod',
                $unidadCod
            )
            ->where(
                'm.mision_estado',
                'A'
            )
            ->where(
                'mi.mitem_estado',
                'A'
            )
            ->whereDate(
                'm.mision_fecha',
                '<=',
                $periodoFin
            )
            ->where(
                function ($subquery) use ($periodoIni) {
                    $subquery
                        ->whereDate(
                            'm.mision_fechafin',
                            '>=',
                            $periodoIni
                        )
                        ->orWhereNull(
                            'm.mision_fechafin'
                        );
                }
            )
            ->select(
                'm.mision_cod',
                'm.mision_descrip',
                'm.mision_nro',
                'm.mision_fecha',
                'm.mision_fechafin',
                'm.mision_puesto_cod',
                'pu.puesto_detalle',
                'us.id as user_id',
                'p.per_cod',
                'p.per_nombres',
                'p.per_apaterno',
                'p.per_amaterno',
                'g.grad_abrev',
                'e.espe_abrev',
                $ciSelect,
                $identificacionSelect
            )
            ->orderBy('m.mision_puesto_cod')
            ->orderBy('m.mision_cod')
            ->orderBy('p.per_apaterno')
            ->orderBy('p.per_amaterno')
            ->orderBy('p.per_nombres')
            ->distinct()
            ->get();

        return $query
            ->map(
                function ($item) use (
                    $unidad,
                    $division,
                    $divisionCod,
                    $unidadCod
                ) {
                    $nombre = trim(
                        implode(
                            ' ',
                            array_filter(
                                [
                                    $item->grad_abrev ?? null,
                                    $item->espe_abrev ?? null,
                                    $item->per_nombres ?? null,
                                    $item->per_apaterno ?? null,
                                    $item->per_amaterno ?? null,
                                ]
                            )
                        )
                    );

                    return [
                        'division_cod' => $divisionCod,
                        'division' => $division?->uni_detalle,
                        'division_abrev' => $division?->uni_abrev,

                        'unidad_cod' => $unidadCod,
                        'unidad' => $unidad?->uni_detalle,
                        'unidad_abrev' => $unidad?->uni_abrev,

                        'puesto_cod' => $item->mision_puesto_cod
                            ? (int) $item->mision_puesto_cod
                            : null,
                        'puesto' => $item->puesto_detalle,
                        'puesto_tipo' => null,

                        'mision_cod' => $item->mision_cod,
                        'mision' => $item->mision_descrip,
                        'mision_nro' => $item->mision_nro,
                        'mision_fecha' => $item->mision_fecha,
                        'mision_fechafin' => $item->mision_fechafin,

                        'per_cod' => $item->per_cod,
                        'user_id' => $item->user_id,
                        'personal' => $nombre,
                        'grado' => $item->grad_abrev,
                        'especialidad' => $item->espe_abrev,
                        'ci' => $item->ci,
                        'codigo_identificacion' =>
                        $item->codigo_identificacion,

                        'fecha_inicio' => $item->mision_fecha,
                        'fecha_fin' => $item->mision_fechafin,
                        'estado' => 'OPERANDO',
                        'observacion' => null,
                    ];
                }
            )
            ->unique(
                function ($item) {
                    return implode(
                        '|',
                        [
                            $item['mision_cod'] ?? '',
                            $item['puesto_cod'] ?? '',
                            $item['user_id'] ?? '',
                        ]
                    );
                }
            )
            ->values();
    }

    /*
    |--------------------------------------------------------------------------
    | NORMALIZAR RESUMEN DE UN DETALLE
    |--------------------------------------------------------------------------
    */
    private function resumenDetalles($detalles): array
    {
        return [
            'total_personal' => $detalles
                ->pluck('user_id')
                ->filter()
                ->unique()
                ->count(),

            'total_puestos' => $detalles
                ->filter(
                    fn($item) => !empty($item['puesto_cod'])
                )
                ->map(
                    fn($item) => ($item['unidad_cod'] ?? '') . '-' .
                        ($item['puesto_cod'] ?? '')
                )
                ->unique()
                ->count(),

            'total_misiones' => $detalles
                ->pluck('mision_cod')
                ->filter()
                ->unique()
                ->count(),

            'total_registros' => $detalles->count(),
        ];
    }

    /*
    |--------------------------------------------------------------------------
    | GUARDAR DETALLES DEL REPORTE
    |--------------------------------------------------------------------------
    */
    private function reemplazarDetallesReporte(
        ReporteOperativo $reporte,
        $detalles
    ): void {
        ReporteOperativoDetalle::where(
            'rodet_repop_cod',
            $reporte->repop_cod
        )->delete();

        foreach ($detalles as $detalle) {
            $modelo = new ReporteOperativoDetalle();

            $datos = [
                'rodet_repop_cod' => $reporte->repop_cod,
                'rodet_div_cod' => $detalle['division_cod'] ?? null,
                'rodet_division' => $detalle['division'] ?? null,
                'rodet_division_abrev' =>
                $detalle['division_abrev'] ?? null,
                'rodet_uni_cod' => $detalle['unidad_cod'] ?? null,
                'rodet_unidad' => $detalle['unidad'] ?? null,
                'rodet_unidad_abrev' =>
                $detalle['unidad_abrev'] ?? null,
                'rodet_puesto_cod' => $detalle['puesto_cod'] ?? null,
                'rodet_puesto' => $detalle['puesto'] ?? null,
                'rodet_puesto_tipo' => $detalle['puesto_tipo'] ?? null,
                'rodet_mision_cod' => $detalle['mision_cod'] ?? null,
                'rodet_mision' => $detalle['mision'] ?? null,
                'rodet_mision_nro' => $detalle['mision_nro'] ?? null,
                'rodet_mision_fecha' => $detalle['mision_fecha'] ?? null,
                'rodet_mision_fechafin' =>
                $detalle['mision_fechafin'] ?? null,
                'rodet_per_cod' => $detalle['per_cod'] ?? null,
                'rodet_user_id' => $detalle['user_id'] ?? null,
                'rodet_personal' => $detalle['personal'] ?? null,
                'rodet_grado' => $detalle['grado'] ?? null,
                'rodet_especialidad' => $detalle['especialidad'] ?? null,
                'rodet_ci' => $detalle['ci'] ?? null,
                'rodet_codigo_identificacion' =>
                $detalle['codigo_identificacion'] ?? null,
                'rodet_fecha_inicio' => $detalle['fecha_inicio'] ?? null,
                'rodet_fecha_fin' => $detalle['fecha_fin'] ?? null,
                'rodet_estado' => $detalle['estado'] ?? null,
                'rodet_observacion' => $detalle['observacion'] ?? null,
            ];

            $modelo->forceFill(
                $this->filtrarColumnasModelo(
                    $modelo,
                    $datos
                )
            );

            $modelo->save();
        }
    }

    /*
    |--------------------------------------------------------------------------
    | SERIALIZAR REPORTE PARA EL FRONTEND
    |--------------------------------------------------------------------------
    */
    private function reporteFrontend(ReporteOperativo $reporte): array
    {
        return array_merge(
            $reporte->toArray(),
            [
                'periodo_ini' => $reporte->repop_periodo_ini,
                'periodo_fin' => $reporte->repop_periodo_fin,
                'fecha_envio' => $reporte->repop_fecha_envio,
                'fecha_recepcion' => $reporte->repop_fecha_recepcion,
                'fecha_revision' => $reporte->repop_fecha_revision,
                'resumen' => $reporte->repop_resumen ?? null,
            ]
        );
    }

    /*
    |==========================================================================
    | P-3
    |==========================================================================
    */

    /*
    |--------------------------------------------------------------------------
    | P-3 - PREVISUALIZAR REPORTE DE SU UNIDAD
    |--------------------------------------------------------------------------
    */
    public function previewUnidad(Request $request)
    {
        if (!$this->esRol('P-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL P-3 PUEDE GENERAR EL REPORTE DE SU UNIDAD',
                ],
                403
            );
        }

        $periodo = $this->fechaReporteDiario($request);

        if (!$periodo['ok']) {
            return $periodo['response'];
        }

        $contexto = $this->contextoP3();

        if (!$contexto['ok']) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' => $contexto['message'],
                ],
                422
            );
        }

        $unidad = $contexto['unidad'];
        $division = $contexto['division'];

        $detalles = $this->detalleUnidad(
            $unidad->uni_cod,
            $division->uni_cod,
            $periodo['periodo_ini'],
            $periodo['periodo_fin']
        );

        $resumen = $this->resumenDetalles($detalles);

        $clave =
            'UNIDAD-' .
            $unidad->uni_cod . '-' .
            str_replace('-', '', $periodo['periodo_ini']) . '-' .
            str_replace('-', '', $periodo['periodo_fin']);

        $reporteExistente = ReporteOperativo::where(
            'repop_clave',
            $clave
        )
            ->where('repop_activo', 'A')
            ->first();

        return response()->json(
            [
                'message' => 200,
                'periodo' => [
                    'inicio' => $periodo['periodo_ini'],
                    'fin' => $periodo['periodo_fin'],
                ],
                'division' => [
                    'uni_cod' => $division->uni_cod,
                    'uni_detalle' => $division->uni_detalle,
                    'uni_abrev' => $division->uni_abrev,
                ],
                'unidad' => [
                    'uni_cod' => $unidad->uni_cod,
                    'uni_detalle' => $unidad->uni_detalle,
                    'uni_abrev' => $unidad->uni_abrev,
                ],
                'resumen' => $resumen,
                'detalles' => $detalles,
                'reporte' => $reporteExistente
                    ? $this->reporteFrontend($reporteExistente)
                    : null,
            ]
        );
    }

    /*
    |--------------------------------------------------------------------------
    | P-3 - GUARDAR / CORREGIR BORRADOR
    |--------------------------------------------------------------------------
    */
    public function guardarBorradorUnidad(Request $request)
    {
        if (!$this->esRol('P-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL P-3 PUEDE CREAR REPORTES DE UNIDAD',
                ],
                403
            );
        }

        $periodo = $this->fechaReporteDiario($request);

        if (!$periodo['ok']) {
            return $periodo['response'];
        }

        $contexto = $this->contextoP3();

        if (!$contexto['ok']) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' => $contexto['message'],
                ],
                422
            );
        }

        $user = auth()->user();
        $unidad = $contexto['unidad'];
        $division = $contexto['division'];

        $detalles = $this->detalleUnidad(
            $unidad->uni_cod,
            $division->uni_cod,
            $periodo['periodo_ini'],
            $periodo['periodo_fin']
        );

        $clave =
            'UNIDAD-' .
            $unidad->uni_cod . '-' .
            str_replace('-', '', $periodo['periodo_ini']) . '-' .
            str_replace('-', '', $periodo['periodo_fin']);

        $g3Usuarios = $this->buscarG3Division(
            $division->uni_cod
        );

        $g3 = $g3Usuarios->count() === 1
            ? $g3Usuarios->first()
            : null;

        try {
            $reporte = DB::transaction(
                function () use (
                    $user,
                    $unidad,
                    $division,
                    $detalles,
                    $periodo,
                    $clave,
                    $g3
                ) {
                    $reporte = ReporteOperativo::where(
                        'repop_clave',
                        $clave
                    )->first();

                    $eraObservado =
                        $reporte &&
                        $reporte->repop_estado === 'OBSERVADO';

                    if (
                        $reporte &&
                        !in_array(
                            $reporte->repop_estado,
                            [
                                'BORRADOR',
                                'OBSERVADO',
                            ],
                            true
                        )
                    ) {
                        throw new \RuntimeException(
                            'EL REPORTE DEL PERIODO YA FUE ENVIADO Y NO PUEDE SER MODIFICADO'
                        );
                    }

                    if (!$reporte) {
                        $reporte = new ReporteOperativo();
                        $reporte->repop_clave = $clave;
                        $reporte->repop_usuareg = $user->id;
                        $reporte->repop_fechareg = now();
                    }

                    $reporte->repop_tipo = 'UNIDAD';
                    $reporte->repop_div_cod = $division->uni_cod;
                    $reporte->repop_uni_cod = $unidad->uni_cod;
                    $reporte->repop_periodo_ini = $periodo['periodo_ini'];
                    $reporte->repop_periodo_fin = $periodo['periodo_fin'];
                    $reporte->repop_titulo =
                        'REPORTE OPERATIVO - ' .
                        ($unidad->uni_abrev ?: $unidad->uni_detalle);
                    $reporte->repop_estado = 'BORRADOR';
                    $reporte->repop_user_emisor = $user->id;
                    $reporte->repop_user_destino = $g3?->id;
                    $reporte->repop_activo = 'A';
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->repop_resumen =
                        $this->resumenDetalles($detalles);

                    if ($eraObservado) {
                        $reporte->repop_observacion = null;
                        $reporte->repop_fecha_envio = null;
                        $reporte->repop_fecha_recepcion = null;
                        $reporte->repop_fecha_revision = null;
                    }

                    $reporte->save();

                    if ($eraObservado) {
                        $this->marcarNotificacionesLeidas(
                            $reporte->repop_cod,
                            $user->id,
                            ['REPORTE_OBSERVADO']
                        );
                    }

                    $this->reemplazarDetallesReporte(
                        $reporte,
                        $detalles
                    );

                    return $reporte;
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'BORRADOR GUARDADO CORRECTAMENTE',
                    'reporte' => $this->reporteFrontend($reporte),
                    'detalles' => $detalles,
                ]
            );
        } catch (\Throwable $e) {
            $codigo = $e instanceof \RuntimeException
                ? 409
                : 500;

            return response()->json(
                [
                    'message' => $codigo,
                    'message_text' => $e->getMessage(),
                ],
                $codigo
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | P-3 - ENVIAR REPORTE AL G-3
    |--------------------------------------------------------------------------
    | BORRADOR -> ENVIADO
    */
    public function enviarUnidadAG3(string $id)
    {
        if (!$this->esRol('P-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL P-3 PUEDE ENVIAR REPORTES DE UNIDAD AL G-3',
                ],
                403
            );
        }

        $user = auth()->user();
        $contexto = $this->contextoP3();

        if (!$contexto['ok']) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' => $contexto['message'],
                ],
                422
            );
        }

        $division = $contexto['division'];

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'UNIDAD')
            ->where('repop_uni_cod', $user->user_uni_cod)
            ->where('repop_user_emisor', $user->id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL REPORTE NO EXISTE O NO PERTENECE A SU UNIDAD',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'BORRADOR') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN ENVIAR REPORTES EN ESTADO BORRADOR',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        $g3Usuarios = $this->buscarG3Division(
            $division->uni_cod
        );

        if ($g3Usuarios->count() !== 1) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'DEBE EXISTIR EXACTAMENTE UN USUARIO G-3 ASIGNADO A LA DIVISIÓN',
                ],
                422
            );
        }

        $g3 = $g3Usuarios->first();

        try {
            DB::transaction(
                function () use (
                    $reporte,
                    $user,
                    $g3,
                    $contexto
                ) {
                    $reporte->repop_estado = 'ENVIADO';
                    $reporte->repop_user_destino = $g3->id;
                    $reporte->repop_fecha_envio = now();
                    $reporte->repop_fecha_recepcion = null;
                    $reporte->repop_fecha_revision = null;
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    $unidad = $contexto['unidad'];

                    $this->crearNotificacion(
                        [
                            'notif_repop_cod' => $reporte->repop_cod,
                            'notif_tipo' => 'NUEVO_REPORTE_UNIDAD',
                            'notif_titulo' => 'NUEVO REPORTE DE UNIDAD',
                            'notif_mensaje' =>
                            'El P-3 de ' .
                                $unidad->uni_detalle .
                                ' envió el reporte correspondiente al periodo ' .
                                Carbon::parse($reporte->repop_periodo_ini)->format('d/m/Y') .
                                ' - ' .
                                Carbon::parse($reporte->repop_periodo_fin)->format('d/m/Y') . '.',
                            'notif_user_emisor' => $user->id,
                            'notif_user_destino' => $g3->id,
                            'notif_prioridad' => 'IMPORTANTE',
                            'notif_ruta' =>
                            '/reportes-operativos/' .
                                $reporte->repop_cod,
                            'notif_datos' => [
                                'reporte_id' => $reporte->repop_cod,
                                'estado' => 'ENVIADO',
                            ],
                            'notif_usuareg' => $user->id,
                        ]
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'REPORTE ENVIADO CORRECTAMENTE AL G-3',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO ENVIAR EL REPORTE AL G-3',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |==========================================================================
    | G-3 - REPORTES DE UNIDAD
    |==========================================================================
    */

    /*
    |--------------------------------------------------------------------------
    | G-3 - BANDEJA DE REPORTES DE UNIDADES
    |--------------------------------------------------------------------------
    */

    public function reportesRecibidosG3(Request $request)
    {
        /*
    |--------------------------------------------------------------------------
    | VALIDAR ROL
    |--------------------------------------------------------------------------
    */
        if (!$this->esRol('G-3')) {

            return response()->json(
                [
                    'message' => 403,

                    'message_text' =>
                    'SOLO EL G-3 PUEDE CONSULTAR REPORTES DE SU DIVISIÓN',
                ],
                403
            );
        }


        $user = auth()->user();


        /*
    |--------------------------------------------------------------------------
    | REPORTES DE UNIDADES DE SU DIVISIÓN
    |--------------------------------------------------------------------------
    */
        $reportes =
            ReporteOperativo::with(
                [
                    'unidad',
                    'emisor',
                    'detalles',
                ]
            )
            ->where(
                'repop_tipo',
                'UNIDAD'
            )

            ->where(
                'repop_div_cod',
                $user->user_uni_cod
            )

            ->where(
                'repop_activo',
                'A'
            )

            ->orderByDesc(
                'repop_periodo_fin'
            )

            ->orderByDesc(
                'repop_cod'
            )

            ->get()

            ->map(
                function ($reporte) {

                    /*
                    |--------------------------------------------------------------------------
                    | TOTAL DE PERSONAL
                    |--------------------------------------------------------------------------
                    |
                    | Se obtiene directamente del detalle almacenado
                    | en el reporte.
                    |
                    | Un mismo militar puede aparecer en más de un registro,
                    | por eso contamos user_id únicos.
                    |
                    */
                    $totalPersonal =
                        $reporte
                        ->detalles
                        ->pluck(
                            'rodet_user_id'
                        )
                        ->filter()
                        ->unique()
                        ->count();


                    /*
                    |--------------------------------------------------------------------------
                    | RESUMEN
                    |--------------------------------------------------------------------------
                    */
                    $resumen =
                        is_array(
                            $reporte->repop_resumen
                        )
                        ? $reporte->repop_resumen
                        : [];


                    /*
                    |--------------------------------------------------------------------------
                    | CORREGIR TOTAL PERSONAL
                    |--------------------------------------------------------------------------
                    */
                    $resumen['total_personal'] =
                        $totalPersonal;


                    return array_merge(
                        $this->reporteFrontend(
                            $reporte
                        ),
                        [
                            /*
                            |--------------------------------------------------------------------------
                            | UNIDAD
                            |--------------------------------------------------------------------------
                            */
                            'unidad' =>
                            $reporte->unidad
                                ? [
                                    'uni_cod' =>
                                    $reporte
                                        ->unidad
                                        ->uni_cod,

                                    'uni_detalle' =>
                                    $reporte
                                        ->unidad
                                        ->uni_detalle,

                                    'uni_abrev' =>
                                    $reporte
                                        ->unidad
                                        ->uni_abrev,
                                ]
                                : null,


                            /*
                            |--------------------------------------------------------------------------
                            | EMISOR
                            |--------------------------------------------------------------------------
                            */
                            'emisor' =>
                            $reporte->emisor
                                ? [
                                    'id' =>
                                    $reporte
                                        ->emisor
                                        ->id,

                                    'name' =>
                                    $reporte
                                        ->emisor
                                        ->name,
                                ]
                                : null,


                            /*
                            |--------------------------------------------------------------------------
                            | TOTALES PARA EL FRONTEND
                            |--------------------------------------------------------------------------
                            |
                            | Dejamos los alias para compatibilidad
                            | con la bandeja actual.
                            |
                            */
                            'total_personal' =>
                            $totalPersonal,

                            'personal' =>
                            $totalPersonal,

                            'repop_resumen' =>
                            $resumen,

                            'resumen' =>
                            $resumen,
                        ]
                    );
                }
            );


        /*
    |--------------------------------------------------------------------------
    | RESPUESTA
    |--------------------------------------------------------------------------
    */
        return response()->json(
            [
                'message' => 200,

                'message_text' =>
                'REPORTES DE UNIDADES OBTENIDOS CORRECTAMENTE',

                'reportes' =>
                $reportes,
            ]
        );
    }

    /*
    |--------------------------------------------------------------------------
    | G-3 - RECIBIR REPORTE DE UNIDAD
    |--------------------------------------------------------------------------
    | ENVIADO -> RECIBIDO
    */
    public function recibirReporteG3(string $id)
    {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE RECIBIR REPORTES DE SU DIVISIÓN',
                ],
                403
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'UNIDAD')
            ->where('repop_div_cod', $user->user_uni_cod)
            ->where('repop_user_destino', $user->id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL REPORTE NO EXISTE O NO PERTENECE A SU DIVISIÓN',
                ],
                404
            );
        }

        if (
            !in_array(
                $reporte->repop_estado,
                ['ENVIADO', 'RECIBIDO'],
                true
            )
        ) {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'EL REPORTE NO SE ENCUENTRA EN UN ESTADO VÁLIDO PARA SU RECEPCIÓN',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        try {
            DB::transaction(
                function () use ($reporte, $user) {
                    if ($reporte->repop_estado === 'ENVIADO') {
                        $reporte->repop_estado = 'RECIBIDO';
                        $reporte->repop_fecha_recepcion = now();
                        $reporte->repop_usuamod = $user->id;
                        $reporte->repop_fechamod = now();
                        $reporte->save();
                    }

                    $this->marcarNotificacionesLeidas(
                        $reporte->repop_cod,
                        $user->id
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'REPORTE RECIBIDO CORRECTAMENTE',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO REGISTRAR LA RECEPCIÓN DEL REPORTE',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | G-3 - OBSERVAR REPORTE DE UNIDAD
    |--------------------------------------------------------------------------
    | RECIBIDO -> OBSERVADO
    */
    public function observarReporteG3(
        Request $request,
        string $id
    ) {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE OBSERVAR REPORTES DE SU DIVISIÓN',
                ],
                403
            );
        }

        $validator = Validator::make(
            $request->all(),
            [
                'observacion' => [
                    'required',
                    'string',
                    'min:5',
                    'max:2000',
                ],
            ]
        );

        if ($validator->fails()) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'DEBE REGISTRAR UNA OBSERVACIÓN VÁLIDA',
                    'errors' => $validator->errors(),
                ],
                422
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'UNIDAD')
            ->where('repop_div_cod', $user->user_uni_cod)
            ->where('repop_user_destino', $user->id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL REPORTE NO EXISTE O NO PERTENECE A SU DIVISIÓN',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'RECIBIDO') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN OBSERVAR REPORTES QUE SE ENCUENTREN EN ESTADO RECIBIDO',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        $p3 = User::find($reporte->repop_user_emisor);

        if (!$p3) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'NO SE ENCONTRÓ AL P-3 EMISOR DEL REPORTE',
                ],
                422
            );
        }

        $observacion = trim($request->observacion);

        try {
            DB::transaction(
                function () use (
                    $reporte,
                    $user,
                    $p3,
                    $observacion
                ) {
                    $reporte->repop_estado = 'OBSERVADO';
                    $reporte->repop_observacion = $observacion;
                    $reporte->repop_fecha_revision = now();
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    $this->crearNotificacion(
                        [
                            'notif_repop_cod' => $reporte->repop_cod,
                            'notif_tipo' => 'REPORTE_OBSERVADO',
                            'notif_titulo' =>
                            'REPORTE OBSERVADO POR EL G-3',
                            'notif_mensaje' =>
                            'El reporte fue observado por el G-3. Motivo: ' .
                                $observacion,
                            'notif_user_emisor' => $user->id,
                            'notif_user_destino' => $p3->id,
                            'notif_prioridad' => 'IMPORTANTE',
                            'notif_ruta' =>
                            '/reportes-operativos/' .
                                $reporte->repop_cod,
                            'notif_datos' => [
                                'reporte_id' => $reporte->repop_cod,
                                'observacion' => $observacion,
                                'estado' => 'OBSERVADO',
                            ],
                            'notif_usuareg' => $user->id,
                        ]
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'REPORTE OBSERVADO CORRECTAMENTE. EL P-3 FUE NOTIFICADO.',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO OBSERVAR EL REPORTE',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | G-3 - APROBAR REPORTE DE UNIDAD
    |--------------------------------------------------------------------------
    | RECIBIDO -> APROBADO
    */
    public function aprobarReporteG3(string $id)
    {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE APROBAR REPORTES DE SU DIVISIÓN',
                ],
                403
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'UNIDAD')
            ->where('repop_div_cod', $user->user_uni_cod)
            ->where('repop_user_destino', $user->id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL REPORTE NO EXISTE O NO PERTENECE A SU DIVISIÓN',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'RECIBIDO') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN APROBAR REPORTES QUE SE ENCUENTREN EN ESTADO RECIBIDO',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        $p3 = User::find($reporte->repop_user_emisor);

        try {
            DB::transaction(
                function () use ($reporte, $user, $p3) {
                    $reporte->repop_estado = 'APROBADO';
                    $reporte->repop_observacion = null;
                    $reporte->repop_fecha_revision = now();
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    if ($p3) {
                        $this->crearNotificacion(
                            [
                                'notif_repop_cod' => $reporte->repop_cod,
                                'notif_tipo' => 'REPORTE_APROBADO',
                                'notif_titulo' =>
                                'REPORTE APROBADO POR EL G-3',
                                'notif_mensaje' =>
                                'El reporte fue aprobado por el G-3 y se encuentra disponible para el consolidado de la División.',
                                'notif_user_emisor' => $user->id,
                                'notif_user_destino' => $p3->id,
                                'notif_prioridad' => 'NORMAL',
                                'notif_ruta' =>
                                '/reportes-operativos/' .
                                    $reporte->repop_cod,
                                'notif_datos' => [
                                    'reporte_id' => $reporte->repop_cod,
                                    'estado' => 'APROBADO',
                                ],
                                'notif_usuareg' => $user->id,
                            ]
                        );
                    }
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'REPORTE APROBADO CORRECTAMENTE POR EL G-3',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO APROBAR EL REPORTE',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }
    /*
|--------------------------------------------------------------------------
| CONTROL DIARIO DE REPORTES DE UNA DIVISIÓN
|--------------------------------------------------------------------------
|
| Verifica todas las Unidades ACTIVAS dependientes directamente
| de una División para una fecha exacta.
|
| IMPORTANTE:
|
| - SIN REPORTE/BORRADOR no enviado = faltante.
| - ENVIADO/RECIBIDO/OBSERVADO = enviado, pero no aprobado.
| - APROBADO = enviado y disponible para consolidación.
|
| No determina incumplimiento horario porque actualmente
| el sistema no tiene una hora límite configurada.
|
*/
    private function controlDiarioDivision(
        int $divisionCod,
        string $fecha
    ): array {

        /*
    |--------------------------------------------------------------------------
    | DIVISIÓN
    |--------------------------------------------------------------------------
    */
        $division = Unidade::select(
            'uni_cod',
            'uni_detalle',
            'uni_abrev'
        )
            ->where(
                'uni_cod',
                $divisionCod
            )
            ->where(
                'uni_estado',
                'A'
            )
            ->first();


        if (!$division) {

            return [
                'ok' => false,

                'message' =>
                'NO SE ENCONTRÓ LA DIVISIÓN O NO SE ENCUENTRA ACTIVA',
            ];
        }


        /*
    |--------------------------------------------------------------------------
    | TODAS LAS UNIDADES DEPENDIENTES ACTIVAS
    |--------------------------------------------------------------------------
    */
        $unidades =
            Unidade::select(
                'uni_cod',
                'uni_detalle',
                'uni_abrev',
                'uni_codsup'
            )
            ->where(
                'uni_codsup',
                $divisionCod
            )

            ->where(
                'uni_estado',
                'A'
            )

            ->orderBy(
                'uni_detalle'
            )

            ->get();


        /*
    |--------------------------------------------------------------------------
    | REPORTES EXACTAMENTE DE LA FECHA EVALUADA
    |--------------------------------------------------------------------------
    |
    | Un reporte del día anterior NO cuenta.
    |
    */
        $reportes =
            ReporteOperativo::where(
                'repop_tipo',
                'UNIDAD'
            )
            ->where(
                'repop_div_cod',
                $divisionCod
            )

            ->where(
                'repop_activo',
                'A'
            )

            ->whereDate(
                'repop_periodo_ini',
                $fecha
            )

            ->whereDate(
                'repop_periodo_fin',
                $fecha
            )

            ->whereIn(
                'repop_uni_cod',
                $unidades
                    ->pluck('uni_cod')
            )

            ->orderByDesc(
                'repop_cod'
            )

            ->get()

            ->unique(
                'repop_uni_cod'
            )

            ->keyBy(
                'repop_uni_cod'
            );


        /*
    |--------------------------------------------------------------------------
    | REPORTES QUE ALGUNA VEZ FUERON ENVIADOS
    |--------------------------------------------------------------------------
    |
    | Esto es importante para los reportes observados:
    |
    | OBSERVADO -> corrección -> BORRADOR
    |
    | Aunque temporalmente vuelva a BORRADOR,
    | la Unidad ya realizó el envío inicial.
    |
    */
        $codigosReportes =
            $reportes
            ->pluck('repop_cod')
            ->filter()
            ->values();


        $reportesConEnvioPrevio =
            $codigosReportes->isEmpty()
            ? collect()
            : NotificacionOperativa::whereIn(
                'notif_repop_cod',
                $codigosReportes
            )
            ->where(
                'notif_tipo',
                'NUEVO_REPORTE_UNIDAD'
            )

            ->where(
                'notif_activo',
                'A'
            )

            ->pluck(
                'notif_repop_cod'
            )

            ->unique();


        /*
    |--------------------------------------------------------------------------
    | EVALUAR CADA UNIDAD
    |--------------------------------------------------------------------------
    */
        $detalle =
            $unidades
            ->map(
                function ($unidad) use (
                    $reportes,
                    $reportesConEnvioPrevio,
                    $fecha
                ) {

                    $reporte =
                        $reportes->get(
                            $unidad->uni_cod
                        );


                    if (!$reporte) {

                        return [
                            'uni_cod' =>
                            $unidad->uni_cod,

                            'uni_detalle' =>
                            $unidad->uni_detalle,

                            'uni_abrev' =>
                            $unidad->uni_abrev,

                            'fecha' =>
                            $fecha,

                            'reporte_cod' =>
                            null,

                            'repop_estado' =>
                            null,

                            'estado_control' =>
                            'SIN_REPORTE',

                            'envio_realizado' =>
                            false,

                            'aprobado' =>
                            false,
                        ];
                    }


                    /*
                    |--------------------------------------------------------------------------
                    | ¿LA UNIDAD YA ENVIÓ?
                    |--------------------------------------------------------------------------
                    */
                    $estadoActual =
                        strtoupper(
                            (string)
                            $reporte->repop_estado
                        );


                    $envioRealizado =
                        in_array(
                            $estadoActual,
                            [
                                'ENVIADO',
                                'RECIBIDO',
                                'OBSERVADO',
                                'APROBADO',
                            ],
                            true
                        )
                        ||
                        $reportesConEnvioPrevio
                        ->contains(
                            $reporte->repop_cod
                        );


                    /*
                    |--------------------------------------------------------------------------
                    | ESTADO DE CONTROL
                    |--------------------------------------------------------------------------
                    */
                    if (!$envioRealizado) {

                        $estadoControl =
                            'BORRADOR_NO_ENVIADO';
                    } elseif (
                        $estadoActual ===
                        'APROBADO'
                    ) {

                        $estadoControl =
                            'APROBADO';
                    } elseif (
                        $estadoActual ===
                        'OBSERVADO'
                        ||
                        $estadoActual ===
                        'BORRADOR'
                    ) {

                        $estadoControl =
                            'EN_CORRECCION';
                    } else {

                        $estadoControl =
                            'EN_REVISION';
                    }


                    return [
                        'uni_cod' =>
                        $unidad->uni_cod,

                        'uni_detalle' =>
                        $unidad->uni_detalle,

                        'uni_abrev' =>
                        $unidad->uni_abrev,

                        'fecha' =>
                        $fecha,

                        'reporte_cod' =>
                        $reporte->repop_cod,

                        'repop_estado' =>
                        $reporte->repop_estado,

                        'estado_control' =>
                        $estadoControl,

                        'envio_realizado' =>
                        $envioRealizado,

                        'aprobado' =>
                        $estadoActual ===
                            'APROBADO',
                    ];
                }
            )
            ->values();


        /*
    |--------------------------------------------------------------------------
    | FALTANTES DE ENVÍO
    |--------------------------------------------------------------------------
    */
        $faltantes =
            $detalle
            ->filter(
                fn($item) =>
                !$item['envio_realizado']
            )
            ->values();


        /*
    |--------------------------------------------------------------------------
    | AÚN NO APROBADOS
    |--------------------------------------------------------------------------
    */
        $noAprobados =
            $detalle
            ->filter(
                fn($item) =>
                !$item['aprobado']
            )
            ->values();


        return [
            'ok' =>
            true,

            'fecha' =>
            $fecha,

            'division' => [
                'uni_cod' =>
                $division->uni_cod,

                'uni_detalle' =>
                $division->uni_detalle,

                'uni_abrev' =>
                $division->uni_abrev,
            ],

            'total_unidades' =>
            $detalle->count(),

            'total_enviados' =>
            $detalle
                ->where(
                    'envio_realizado',
                    true
                )
                ->count(),

            'total_faltantes' =>
            $faltantes->count(),

            'total_aprobados' =>
            $detalle
                ->where(
                    'aprobado',
                    true
                )
                ->count(),

            'total_pendientes_aprobacion' =>
            $noAprobados->count(),

            /*
        |--------------------------------------------------------------------------
        | COMPLETITUD
        |--------------------------------------------------------------------------
        */
            'envio_completo' =>
            $detalle->isNotEmpty()
                &&
                $faltantes->isEmpty(),

            'consolidacion_completa' =>
            $detalle->isNotEmpty()
                &&
                $noAprobados->isEmpty(),

            /*
        |--------------------------------------------------------------------------
        | HORA LÍMITE
        |--------------------------------------------------------------------------
        |
        | Aún no configurada.
        |
        */
            'hora_limite_configurada' =>
            false,

            'hora_limite' =>
            null,

            'unidades_faltantes' =>
            $faltantes,

            'unidades_no_aprobadas' =>
            $noAprobados,

            'unidades' =>
            $detalle,
        ];
    }

    /*
|--------------------------------------------------------------------------
| VALIDAR INTEGRIDAD DE UN CONSOLIDADO
|--------------------------------------------------------------------------
|
| Un consolidado solamente es válido cuando:
|
| 1. Todas las unidades activas de la División enviaron reporte.
| 2. Todos esos reportes están APROBADOS.
| 3. El consolidado contiene exactamente esos reportes fuente.
|
*/
    private function validarIntegridadConsolidado(
        ReporteOperativo $consolidado
    ): array {

        if ($consolidado->repop_tipo !== 'DIVISION') {

            return [
                'ok' => false,
                'message' =>
                'EL REPORTE INDICADO NO ES UN CONSOLIDADO DE DIVISIÓN',
            ];
        }


        $fechaInicio =
            \Illuminate\Support\Carbon::parse(
                $consolidado->repop_periodo_ini
            )->format('Y-m-d');


        $fechaFin =
            \Illuminate\Support\Carbon::parse(
                $consolidado->repop_periodo_fin
            )->format('Y-m-d');


        /*
    |--------------------------------------------------------------------------
    | EL CONSOLIDADO ES DIARIO
    |--------------------------------------------------------------------------
    */
        if ($fechaInicio !== $fechaFin) {

            return [
                'ok' => false,

                'message' =>
                'EL CONSOLIDADO DEBE CORRESPONDER A UNA ÚNICA FECHA OPERATIVA',
            ];
        }


        /*
    |--------------------------------------------------------------------------
    | CONTROL REAL DE TODAS LAS UNIDADES
    |--------------------------------------------------------------------------
    */
        $control =
            $this->controlDiarioDivision(
                (int) $consolidado->repop_div_cod,
                $fechaInicio
            );


        if (!$control['ok']) {

            return [
                'ok' => false,

                'message' =>
                $control['message'],

                'control' =>
                $control,
            ];
        }


        /*
    |--------------------------------------------------------------------------
    | FALTAN REPORTES DE UNIDAD
    |--------------------------------------------------------------------------
    */
        if (!$control['envio_completo']) {

            $faltantes =
                collect(
                    $control['unidades_faltantes']
                )
                ->pluck('uni_detalle')
                ->filter()
                ->values();


            return [
                'ok' => false,

                'tipo' =>
                'REPORTES_FALTANTES',

                'message' =>
                'EL CONSOLIDADO ESTÁ INCOMPLETO. ' .
                    'FALTAN REPORTES DE ' .
                    $faltantes->count() .
                    ' UNIDAD(ES) PARA EL ' .
                    $fechaInicio .
                    ': ' .
                    $faltantes->implode(', '),

                'control' =>
                $control,
            ];
        }


        /*
    |--------------------------------------------------------------------------
    | EXISTEN REPORTES AÚN NO APROBADOS
    |--------------------------------------------------------------------------
    */
        if (!$control['consolidacion_completa']) {

            $pendientes =
                collect(
                    $control['unidades_no_aprobadas']
                )
                ->map(
                    function ($item) {

                        return
                            $item['uni_detalle'] .
                            ' (' .
                            (
                                $item['repop_estado']
                                ?? $item['estado_control']
                                ?? 'PENDIENTE'
                            ) .
                            ')';
                    }
                )
                ->values();


            return [
                'ok' => false,

                'tipo' =>
                'REPORTES_NO_APROBADOS',

                'message' =>
                'NO TODOS LOS REPORTES DE UNIDAD ESTÁN APROBADOS. ' .
                    'PENDIENTES: ' .
                    $pendientes->implode(', '),

                'control' =>
                $control,
            ];
        }


        /*
    |--------------------------------------------------------------------------
    | REPORTES QUE DEBERÍA CONTENER EL CONSOLIDADO
    |--------------------------------------------------------------------------
    */
        $reportesEsperados =
            ReporteOperativo::where(
                'repop_tipo',
                'UNIDAD'
            )
            ->where(
                'repop_div_cod',
                $consolidado->repop_div_cod
            )

            ->where(
                'repop_estado',
                'APROBADO'
            )

            ->where(
                'repop_activo',
                'A'
            )

            ->whereDate(
                'repop_periodo_ini',
                $fechaInicio
            )

            ->whereDate(
                'repop_periodo_fin',
                $fechaInicio
            )

            ->orderByDesc(
                'repop_cod'
            )

            ->get([
                'repop_cod',
                'repop_uni_cod',
            ])

            ->unique(
                'repop_uni_cod'
            )

            ->values();


        /*
    |--------------------------------------------------------------------------
    | REPORTES QUE REALMENTE ESTÁN DENTRO DEL CONSOLIDADO
    |--------------------------------------------------------------------------
    */
        $fuentesActuales =
            ReporteOperativoFuente::where(
                'rofue_reporte_destino',
                $consolidado->repop_cod
            )
            ->where(
                'rofue_estado',
                'A'
            )

            ->pluck(
                'rofue_reporte_fuente'
            )

            ->map(
                fn($id) => (int) $id
            )

            ->sort()

            ->values();


        $fuentesEsperadas =
            $reportesEsperados
            ->pluck(
                'repop_cod'
            )

            ->map(
                fn($id) => (int) $id
            )

            ->sort()

            ->values();


        /*
    |--------------------------------------------------------------------------
    | CONSOLIDADO DESACTUALIZADO
    |--------------------------------------------------------------------------
    |
    | Esto protege, por ejemplo, al Consolidado #9:
    | fue creado cuando solamente existía el Reporte #8.
    |
    */
        if (
            $fuentesActuales->all()
            !==
            $fuentesEsperadas->all()
        ) {

            return [
                'ok' => false,

                'tipo' =>
                'CONSOLIDADO_DESACTUALIZADO',

                'message' =>
                'EL CONSOLIDADO NO CONTIENE TODOS LOS REPORTES APROBADOS ACTUALES. ' .
                    'DEBE REGENERARSE ANTES DE CONTINUAR.',

                'control' =>
                $control,

                'reportes_esperados' =>
                $fuentesEsperadas,

                'reportes_consolidados' =>
                $fuentesActuales,
            ];
        }


        return [
            'ok' => true,

            'message' =>
            'CONSOLIDADO COMPLETO',

            'control' =>
            $control,
        ];
    }

    /*
|--------------------------------------------------------------------------
| G-3 - CONTROL DIARIO DE REPORTES DE SU DIVISIÓN
|--------------------------------------------------------------------------
|
| Permite consultar, para una fecha exacta:
|
| - todas las unidades dependientes activas
| - cuáles enviaron reporte
| - cuáles están pendientes
| - cuáles están aprobadas
| - si la División está completa para consolidar
|
*/
    public function controlDiarioReportesG3(
        Request $request
    ) {
        /*
    |--------------------------------------------------------------------------
    | VALIDAR ROL
    |--------------------------------------------------------------------------
    */
        if (!$this->esRol('G-3')) {

            return response()->json(
                [
                    'message' => 403,

                    'message_text' =>
                    'SOLO EL G-3 PUEDE CONSULTAR EL CONTROL DIARIO DE SU DIVISIÓN',
                ],
                403
            );
        }


        /*
    |--------------------------------------------------------------------------
    | VALIDAR FECHA
    |--------------------------------------------------------------------------
    */
        $validator = Validator::make(
            $request->all(),
            [
                'fecha' => [
                    'required',
                    'date_format:Y-m-d',
                ],
            ],
            [
                'fecha.required' =>
                'Debe indicar la fecha que desea controlar.',

                'fecha.date_format' =>
                'La fecha debe tener el formato AAAA-MM-DD.',
            ]
        );


        if ($validator->fails()) {

            return response()->json(
                [
                    'message' => 422,

                    'message_text' =>
                    'LA FECHA DEL CONTROL DIARIO NO ES VÁLIDA',

                    'errors' =>
                    $validator->errors(),
                ],
                422
            );
        }


        /*
    |--------------------------------------------------------------------------
    | DIVISIÓN DEL G-3 AUTENTICADO
    |--------------------------------------------------------------------------
    */
        $user =
            auth()->user();


        if (
            !$user
            ||
            !$user->user_uni_cod
        ) {

            return response()->json(
                [
                    'message' => 422,

                    'message_text' =>
                    'EL G-3 NO TIENE UNA DIVISIÓN ASIGNADA',
                ],
                422
            );
        }


        /*
    |--------------------------------------------------------------------------
    | EJECUTAR CONTROL
    |--------------------------------------------------------------------------
    */
        $control =
            $this->controlDiarioDivision(
                (int) $user->user_uni_cod,
                $request->fecha
            );


        if (!$control['ok']) {

            return response()->json(
                [
                    'message' => 422,

                    'message_text' =>
                    $control['message'],
                ],
                422
            );
        }


        /*
    |--------------------------------------------------------------------------
    | RESPUESTA
    |--------------------------------------------------------------------------
    */
        return response()->json(
            [
                'message' => 200,

                'message_text' =>
                'CONTROL DIARIO OBTENIDO CORRECTAMENTE',

                'control' =>
                $control,
            ]
        );
    }

    /*
|--------------------------------------------------------------------------
| G-3 - NOTIFICAR REPORTES DIARIOS PENDIENTES
|--------------------------------------------------------------------------
|
| El G-3 puede enviar un recordatorio interno a los P-3 de
| las Unidades que todavía no enviaron su reporte diario.
|
| Protecciones:
|
| - vuelve a comprobar los pendientes antes de notificar
| - no elige arbitrariamente entre varios P-3
| - no crea duplicados para Unidad + fecha
| - no requiere repop_cod porque el reporte puede no existir
|
*/
public function notificarReportesPendientesG3(
    Request $request
) {
    /*
    |--------------------------------------------------------------------------
    | VALIDAR ROL
    |--------------------------------------------------------------------------
    */
    if (!$this->esRol('G-3')) {

        return response()->json(
            [
                'message' => 403,

                'message_text' =>
                    'SOLO EL G-3 PUEDE NOTIFICAR REPORTES PENDIENTES',
            ],
            403
        );
    }


    /*
    |--------------------------------------------------------------------------
    | VALIDAR FECHA
    |--------------------------------------------------------------------------
    */
    $validator = Validator::make(
        $request->all(),
        [
            'fecha' => [
                'required',
                'date_format:Y-m-d',
            ],
        ],
        [
            'fecha.required' =>
                'Debe indicar la fecha del reporte pendiente.',

            'fecha.date_format' =>
                'La fecha debe tener el formato AAAA-MM-DD.',
        ]
    );


    if ($validator->fails()) {

        return response()->json(
            [
                'message' => 422,

                'message_text' =>
                    'LA FECHA DEL CONTROL DIARIO NO ES VÁLIDA',

                'errors' =>
                    $validator->errors(),
            ],
            422
        );
    }


    $user =
        auth()->user();


    if (
        !$user
        ||
        !$user->user_uni_cod
    ) {

        return response()->json(
            [
                'message' => 422,

                'message_text' =>
                    'EL G-3 NO TIENE UNA DIVISIÓN ASIGNADA',
            ],
            422
        );
    }


    $fecha =
        $request->fecha;


    /*
    |--------------------------------------------------------------------------
    | VOLVER A COMPROBAR LOS PENDIENTES
    |--------------------------------------------------------------------------
    |
    | No confiamos únicamente en la información que muestra
    | actualmente el navegador.
    |
    */
    $control =
        $this->controlDiarioDivision(
            (int) $user->user_uni_cod,
            $fecha
        );


    if (!$control['ok']) {

        return response()->json(
            [
                'message' => 422,

                'message_text' =>
                    $control['message'],
            ],
            422
        );
    }


    $faltantes =
        collect(
            $control['unidades_faltantes']
            ?? []
        );


    /*
    |--------------------------------------------------------------------------
    | YA NO EXISTEN PENDIENTES
    |--------------------------------------------------------------------------
    */
    if ($faltantes->isEmpty()) {

        return response()->json(
            [
                'message' => 200,

                'message_text' =>
                    'NO EXISTEN REPORTES PENDIENTES PARA LA FECHA SELECCIONADA',

                'fecha' =>
                    $fecha,

                'notificados' =>
                    [],

                'ya_notificados' =>
                    [],

                'sin_p3' =>
                    [],

                'multiples_p3' =>
                    [],
            ]
        );
    }


    $divisionNombre =
        $control['division']['uni_detalle']
        ?? 'LA DIVISIÓN';


    /*
    |--------------------------------------------------------------------------
    | RESULTADOS
    |--------------------------------------------------------------------------
    */
    $resultado = [

        'notificados' =>
            [],

        'ya_notificados' =>
            [],

        'sin_p3' =>
            [],

        'multiples_p3' =>
            [],
    ];


    try {

        DB::transaction(
            function () use (
                $faltantes,
                $user,
                $fecha,
                $control,
                $divisionNombre,
                &$resultado
            ) {

                foreach (
                    $faltantes as
                    $unidad
                ) {

                    $unidadCod =
                        (int) $unidad['uni_cod'];


                    /*
                    |--------------------------------------------------------------------------
                    | BUSCAR P-3 ACTUAL
                    |--------------------------------------------------------------------------
                    */
                    $p3Usuarios =
                        $this->buscarP3Unidad(
                            $unidadCod
                        );


                    /*
                    |--------------------------------------------------------------------------
                    | SIN P-3
                    |--------------------------------------------------------------------------
                    */
                    if (
                        $p3Usuarios->count() === 0
                    ) {

                        $resultado['sin_p3'][] = [

                            'uni_cod' =>
                                $unidadCod,

                            'uni_detalle' =>
                                $unidad['uni_detalle'],
                        ];

                        continue;
                    }


                    /*
                    |--------------------------------------------------------------------------
                    | MÁS DE UN P-3
                    |--------------------------------------------------------------------------
                    */
                    if (
                        $p3Usuarios->count() > 1
                    ) {

                        $resultado['multiples_p3'][] = [

                            'uni_cod' =>
                                $unidadCod,

                            'uni_detalle' =>
                                $unidad['uni_detalle'],

                            'usuarios' =>
                                $p3Usuarios
                                    ->map(
                                        fn($usuario) => [
                                            'id' =>
                                                $usuario->id,

                                            'name' =>
                                                $usuario->name,
                                        ]
                                    )
                                    ->values(),
                        ];

                        continue;
                    }


                    $p3 =
                        $p3Usuarios->first();


                    /*
                    |--------------------------------------------------------------------------
                    | EVITAR DUPLICADO
                    |--------------------------------------------------------------------------
                    |
                    | La misma Unidad + fecha + P-3 solamente
                    | recibe un aviso de este tipo.
                    |
                    */
                    $yaExiste =
                        NotificacionOperativa::where(
                            'notif_tipo',
                            'REPORTE_DIARIO_PENDIENTE'
                        )

                            ->where(
                                'notif_user_destino',
                                $p3->id
                            )

                            ->where(
                                'notif_activo',
                                'A'
                            )

                            ->where(
                                'notif_datos->unidad_cod',
                                $unidadCod
                            )

                            ->where(
                                'notif_datos->fecha',
                                $fecha
                            )

                            ->exists();


                    if ($yaExiste) {

                        $resultado['ya_notificados'][] = [

                            'uni_cod' =>
                                $unidadCod,

                            'uni_detalle' =>
                                $unidad['uni_detalle'],

                            'p3_id' =>
                                $p3->id,

                            'p3' =>
                                $p3->name,
                        ];

                        continue;
                    }


                    /*
                    |--------------------------------------------------------------------------
                    | CREAR NOTIFICACIÓN
                    |--------------------------------------------------------------------------
                    */
                    $this->crearNotificacion(
                        [
                            /*
                            |--------------------------------------------------------------------------
                            | Puede ser NULL porque todavía no existe reporte.
                            |--------------------------------------------------------------------------
                            */
                            'notif_repop_cod' =>
                                null,

                            'notif_tipo' =>
                                'REPORTE_DIARIO_PENDIENTE',

                            'notif_titulo' =>
                                'REPORTE DIARIO PENDIENTE',

                            'notif_mensaje' =>
                                'El G-3 de ' .
                                $divisionNombre .
                                ' informa que el reporte diario correspondiente al ' .
                                Carbon::parse($fecha)->format('d/m/Y') .
                                ' de ' .
                                $unidad['uni_detalle'] .
                                ' todavía se encuentra pendiente. ' .
                                'Registre, revise y envíe su reporte diario al G-3.',

                            'notif_user_emisor' =>
                                $user->id,

                            'notif_user_destino' =>
                                $p3->id,

                            'notif_prioridad' =>
                                'IMPORTANTE',

                            /*
                            |--------------------------------------------------------------------------
                            | MI REPORTE DIARIO
                            |--------------------------------------------------------------------------
                            */
                            'notif_ruta' =>
                                '/reportes-operativos/mi-unidad?fecha=' .
                                $fecha,

                            /*
                            |--------------------------------------------------------------------------
                            | CONTEXTO DEL RECORDATORIO
                            |--------------------------------------------------------------------------
                            */
                            'notif_datos' => [

                                'division_cod' =>
                                    $control['division']['uni_cod']
                                    ?? $user->user_uni_cod,

                                'division' =>
                                    $divisionNombre,

                                'unidad_cod' =>
                                    $unidadCod,

                                'unidad' =>
                                    $unidad['uni_detalle'],

                                'fecha' =>
                                    $fecha,

                                'estado' =>
                                    'PENDIENTE',

                                'origen' =>
                                    'G-3',
                            ],

                            'notif_usuareg' =>
                                $user->id,
                        ]
                    );


                    $resultado['notificados'][] = [

                        'uni_cod' =>
                            $unidadCod,

                        'uni_detalle' =>
                            $unidad['uni_detalle'],

                        'p3_id' =>
                            $p3->id,

                        'p3' =>
                            $p3->name,
                    ];
                }
            }
        );


        /*
        |--------------------------------------------------------------------------
        | RESPUESTA
        |--------------------------------------------------------------------------
        */
        return response()->json(
            [
                'message' => 200,

                'message_text' =>
                    count($resultado['notificados']) > 0

                        ? 'RECORDATORIOS ENVIADOS CORRECTAMENTE'

                        : 'NO SE GENERARON NUEVOS RECORDATORIOS',

                'fecha' =>
                    $fecha,

                'total_pendientes' =>
                    $faltantes->count(),

                'total_notificados' =>
                    count(
                        $resultado['notificados']
                    ),

                'total_ya_notificados' =>
                    count(
                        $resultado['ya_notificados']
                    ),

                'total_sin_p3' =>
                    count(
                        $resultado['sin_p3']
                    ),

                'total_multiples_p3' =>
                    count(
                        $resultado['multiples_p3']
                    ),

                'resultado' =>
                    $resultado,
            ]
        );

    } catch (\Throwable $e) {

        return response()->json(
            [
                'message' => 500,

                'message_text' =>
                    'NO SE PUDIERON ENVIAR LOS RECORDATORIOS DE REPORTES PENDIENTES',

                'error' =>
                    $e->getMessage(),
            ],
            500
        );
    }
}

    /*
    |==========================================================================
    | G-3 - CONSOLIDADO DE DIVISIÓN
    |==========================================================================
    */

    /*
    |--------------------------------------------------------------------------
    | CONSULTAR CONSOLIDADO DIARIO
    |--------------------------------------------------------------------------
    */
    public function consultarConsolidadoDiario(Request $request)
    {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE CONSULTAR EL CONSOLIDADO DE SU DIVISIÓN',
                ],
                403
            );
        }

        $periodo = $this->fechaReporteDiario($request);

        if (!$periodo['ok']) {
            return $periodo['response'];
        }

        $user = auth()->user();

        $clave =
            'DIVISION-' .
            $user->user_uni_cod . '-' .
            str_replace('-', '', $periodo['periodo_ini']) . '-' .
            str_replace('-', '', $periodo['periodo_fin']);

        $reporte = ReporteOperativo::where(
            'repop_clave',
            $clave
        )
            ->where('repop_tipo', 'DIVISION')
            ->where('repop_div_cod', $user->user_uni_cod)
            ->where('repop_activo', 'A')
            ->first();

        return response()->json(
            [
                'message' => 200,
                'existe' => (bool) $reporte,
                'reporte' => $reporte
                    ? $this->reporteFrontend($reporte)
                    : null,
            ]
        );
    }

    /*
    |--------------------------------------------------------------------------
    | G-3 - CREAR / REGENERAR CONSOLIDADO DE DIVISIÓN
    |--------------------------------------------------------------------------
    */
    public function crearConsolidadoDivision(Request $request)
    {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE GENERAR EL CONSOLIDADO DE SU DIVISIÓN',
                ],
                403
            );
        }

        $periodo = $this->fechaReporteDiario($request);

        if (!$periodo['ok']) {
            return $periodo['response'];
        }

        $user = auth()->user();

        $division = Unidade::where(
            'uni_cod',
            $user->user_uni_cod
        )->first();

        if (!$division) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'NO SE ENCONTRÓ LA DIVISIÓN DEL G-3',
                ],
                422
            );
        }

        /*
|--------------------------------------------------------------------------
| VALIDAR QUE TODAS LAS UNIDADES ESTÉN LISTAS
|--------------------------------------------------------------------------
*/
        $control =
            $this->controlDiarioDivision(
                (int) $division->uni_cod,
                $periodo['periodo_ini']
            );


        if (
            !$control['ok']
            ||
            !$control['consolidacion_completa']
        ) {

            return response()->json(
                [
                    'message' => 409,

                    'message_text' =>
                    'NO SE PUEDE GENERAR EL CONSOLIDADO. ' .
                        'TODAS LAS UNIDADES DEPENDIENTES DEBEN TENER ' .
                        'SU REPORTE DEL DÍA APROBADO.',

                    'control' =>
                    $control,
                ],
                409
            );
        }

        $reportesFuente = ReporteOperativo::with([
            'detalles',
            'unidad',
        ])
            ->where('repop_tipo', 'UNIDAD')
            ->where('repop_div_cod', $division->uni_cod)
            ->where('repop_estado', 'APROBADO')
            ->where('repop_activo', 'A')
            ->whereDate(
                'repop_periodo_ini',
                $periodo['periodo_ini']
            )

            ->whereDate(
                'repop_periodo_fin',
                $periodo['periodo_ini']
            )
            ->orderByDesc('repop_cod')
            ->get()
            ->unique('repop_uni_cod')
            ->values();

        if ($reportesFuente->isEmpty()) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'NO EXISTEN REPORTES DE UNIDAD APROBADOS PARA CONSOLIDAR EN LA FECHA SELECCIONADA',
                ],
                422
            );
        }

        $clave =
            'DIVISION-' .
            $division->uni_cod . '-' .
            str_replace('-', '', $periodo['periodo_ini']) . '-' .
            str_replace('-', '', $periodo['periodo_fin']);

        $admin = $this->buscarAdministradorDptoIII();

        try {
            $resultado = DB::transaction(
                function () use (
                    $user,
                    $division,
                    $reportesFuente,
                    $periodo,
                    $clave,
                    $admin
                ) {
                    $reporte = ReporteOperativo::where(
                        'repop_clave',
                        $clave
                    )->first();

                    $eraObservado =
                        $reporte &&
                        $reporte->repop_estado === 'OBSERVADO';

                    if (
                        $reporte &&
                        !in_array(
                            $reporte->repop_estado,
                            ['BORRADOR', 'OBSERVADO'],
                            true
                        )
                    ) {
                        throw new \RuntimeException(
                            'EL CONSOLIDADO YA FUE ENVIADO Y NO PUEDE REGENERARSE EN SU ESTADO ACTUAL'
                        );
                    }

                    if (!$reporte) {
                        $reporte = new ReporteOperativo();
                        $reporte->repop_clave = $clave;
                        $reporte->repop_usuareg = $user->id;
                        $reporte->repop_fechareg = now();
                    }

                    $reporte->repop_tipo = 'DIVISION';
                    $reporte->repop_div_cod = $division->uni_cod;
                    $reporte->repop_uni_cod = null;
                    $reporte->repop_periodo_ini = $periodo['periodo_ini'];
                    $reporte->repop_periodo_fin = $periodo['periodo_fin'];
                    $reporte->repop_titulo =
                        'REPORTE CONSOLIDADO OPERATIVO - ' .
                        ($division->uni_abrev ?: $division->uni_detalle);
                    $reporte->repop_estado = 'BORRADOR';
                    $reporte->repop_user_emisor = $user->id;
                    $reporte->repop_user_destino = $admin?->id;
                    $reporte->repop_activo = 'A';
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();

                    if ($eraObservado) {
                        $reporte->repop_observacion = null;
                        $reporte->repop_fecha_envio = null;
                        $reporte->repop_fecha_recepcion = null;
                        $reporte->repop_fecha_revision = null;
                    }

                    $reporte->save();

                    ReporteOperativoDetalle::where(
                        'rodet_repop_cod',
                        $reporte->repop_cod
                    )->delete();

                    ReporteOperativoFuente::where(
                        'rofue_reporte_destino',
                        $reporte->repop_cod
                    )->delete();

                    $detallesConsolidados = collect();

                    foreach (
                        $reportesFuente as $orden => $fuente
                    ) {
                        $modeloFuente = new ReporteOperativoFuente();

                        $datosFuente = [
                            'rofue_reporte_destino' =>
                            $reporte->repop_cod,
                            'rofue_reporte_fuente' =>
                            $fuente->repop_cod,
                            'rofue_orden' => $orden + 1,
                            'rofue_estado' => 'A',
                            'rofue_usuareg' => $user->id,
                            'rofue_fechareg' => now(),
                        ];

                        $modeloFuente->forceFill(
                            $this->filtrarColumnasModelo(
                                $modeloFuente,
                                $datosFuente
                            )
                        );
                        $modeloFuente->save();

                        foreach ($fuente->detalles as $detalleFuente) {
                            $detalle = [
                                'division_cod' =>
                                $detalleFuente->rodet_div_cod,
                                'division' =>
                                $detalleFuente->rodet_division,
                                'division_abrev' =>
                                $detalleFuente->rodet_division_abrev,
                                'unidad_cod' =>
                                $detalleFuente->rodet_uni_cod,
                                'unidad' =>
                                $detalleFuente->rodet_unidad,
                                'unidad_abrev' =>
                                $detalleFuente->rodet_unidad_abrev,
                                'puesto_cod' =>
                                $detalleFuente->rodet_puesto_cod,
                                'puesto' =>
                                $detalleFuente->rodet_puesto,
                                'puesto_tipo' =>
                                $detalleFuente->rodet_puesto_tipo,
                                'mision_cod' =>
                                $detalleFuente->rodet_mision_cod,
                                'mision' =>
                                $detalleFuente->rodet_mision,
                                'mision_nro' =>
                                $detalleFuente->rodet_mision_nro,
                                'mision_fecha' =>
                                $detalleFuente->rodet_mision_fecha,
                                'mision_fechafin' =>
                                $detalleFuente->rodet_mision_fechafin,
                                'per_cod' =>
                                $detalleFuente->rodet_per_cod,
                                'user_id' =>
                                $detalleFuente->rodet_user_id,
                                'personal' =>
                                $detalleFuente->rodet_personal,
                                'grado' =>
                                $detalleFuente->rodet_grado,
                                'especialidad' =>
                                $detalleFuente->rodet_especialidad,
                                'ci' => $detalleFuente->rodet_ci,
                                'codigo_identificacion' =>
                                $detalleFuente->rodet_codigo_identificacion,
                                'fecha_inicio' =>
                                $detalleFuente->rodet_fecha_inicio,
                                'fecha_fin' =>
                                $detalleFuente->rodet_fecha_fin,
                                'estado' =>
                                $detalleFuente->rodet_estado,
                                'observacion' =>
                                $detalleFuente->rodet_observacion,
                            ];

                            $detallesConsolidados->push($detalle);
                        }
                    }

                    $this->reemplazarDetallesReporte(
                        $reporte,
                        $detallesConsolidados
                    );

                    $resumen = $this->resumenDetalles(
                        $detallesConsolidados
                    );

                    $resumen['total_reportes_fuente'] =
                        $reportesFuente->count();
                    $resumen['total_unidades'] =
                        $reportesFuente
                        ->pluck('repop_uni_cod')
                        ->filter()
                        ->unique()
                        ->count();

                    $reporte->repop_resumen = $resumen;
                    $reporte->save();

                    if ($eraObservado) {
                        $this->marcarNotificacionesLeidas(
                            $reporte->repop_cod,
                            $user->id,
                            ['REPORTE_DIVISION_OBSERVADO']
                        );
                    }

                    return [
                        'reporte' => $reporte,
                        'detalles' => $detallesConsolidados,
                    ];
                }
            );

            $reporte = $resultado['reporte'];
            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'CONSOLIDADO DIARIO GENERADO CORRECTAMENTE',
                    'reporte' => $this->reporteFrontend($reporte),
                    'reportes_fuente' => $reportesFuente
                        ->map(
                            function ($fuente) {
                                return [
                                    'repop_cod' => $fuente->repop_cod,
                                    'repop_clave' => $fuente->repop_clave,
                                    'repop_estado' => $fuente->repop_estado,
                                    'unidad' => $fuente->unidad
                                        ? [
                                            'uni_cod' =>
                                            $fuente->unidad->uni_cod,
                                            'uni_detalle' =>
                                            $fuente->unidad->uni_detalle,
                                            'uni_abrev' =>
                                            $fuente->unidad->uni_abrev,
                                        ]
                                        : null,
                                ];
                            }
                        )
                        ->values(),
                ]
            );
        } catch (\Throwable $e) {
            $codigo = $e instanceof \RuntimeException
                ? 409
                : 500;

            return response()->json(
                [
                    'message' => $codigo,
                    'message_text' => $e->getMessage(),
                ],
                $codigo
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | G-3 - ENVIAR CONSOLIDADO AL DPTO. III
    |--------------------------------------------------------------------------
    | BORRADOR -> ENVIADO
    */
    public function enviarConsolidadoAdmin(string $id)
    {
        if (!$this->esRol('G-3')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL G-3 PUEDE ENVIAR EL CONSOLIDADO AL DPTO. III',
                ],
                403
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'DIVISION')
            ->where('repop_div_cod', $user->user_uni_cod)
            ->where('repop_user_emisor', $user->id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL CONSOLIDADO NO EXISTE O NO PERTENECE A SU DIVISIÓN',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'BORRADOR') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN ENVIAR CONSOLIDADOS EN ESTADO BORRADOR',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        /*
|--------------------------------------------------------------------------
| VALIDAR INTEGRIDAD ANTES DE ENVIAR
|--------------------------------------------------------------------------
*/
        $integridad =
            $this->validarIntegridadConsolidado(
                $reporte
            );


        if (!$integridad['ok']) {

            return response()->json(
                [
                    'message' => 409,

                    'message_text' =>
                    $integridad['message'],

                    'tipo' =>
                    $integridad['tipo']
                        ?? 'CONSOLIDADO_INCOMPLETO',

                    'control' =>
                    $integridad['control']
                        ?? null,
                ],
                409
            );
        }

        $admin = $reporte->repop_user_destino
            ? User::find($reporte->repop_user_destino)
            : $this->buscarAdministradorDptoIII();

        if (!$admin) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'NO EXISTE UN ADMINISTRADOR DEL DPTO. III CONFIGURADO',
                ],
                422
            );
        }

        try {
            DB::transaction(
                function () use ($reporte, $user, $admin) {
                    $reporte->repop_estado = 'ENVIADO';
                    $reporte->repop_user_destino = $admin->id;
                    $reporte->repop_fecha_envio = now();
                    $reporte->repop_fecha_recepcion = null;
                    $reporte->repop_fecha_revision = null;
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    $this->crearNotificacion(
                        [
                            'notif_repop_cod' => $reporte->repop_cod,
                            'notif_tipo' => 'CONSOLIDADO_ENVIADO',
                            'notif_titulo' =>
                            'NUEVO CONSOLIDADO DE DIVISIÓN',
                            'notif_mensaje' =>
                            'La División envió un consolidado operativo para revisión del Dpto. III.',
                            'notif_user_emisor' => $user->id,
                            'notif_user_destino' => $admin->id,
                            'notif_prioridad' => 'IMPORTANTE',
                            'notif_ruta' =>
                            '/reportes-operativos/' .
                                $reporte->repop_cod,
                            'notif_datos' => [
                                'reporte_id' => $reporte->repop_cod,
                                'estado' => 'ENVIADO',
                            ],
                            'notif_usuareg' => $user->id,
                        ]
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'CONSOLIDADO ENVIADO CORRECTAMENTE AL DPTO. III',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO ENVIAR EL CONSOLIDADO AL DPTO. III',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |==========================================================================
    | DPTO. III - CONSOLIDADO
    |==========================================================================
    */

    /*
    |--------------------------------------------------------------------------
    | DPTO. III - RECIBIR CONSOLIDADO
    |--------------------------------------------------------------------------
    | ENVIADO -> RECIBIDO
    */
    public function recibirConsolidadoAdmin(string $id)
    {
        if (!$this->esRol('Super-Admin', 'Admin-Dpto-III')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL ADMINISTRADOR DEL DPTO. III PUEDE RECIBIR CONSOLIDADOS',
                ],
                403
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'DIVISION')
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL CONSOLIDADO NO EXISTE',
                ],
                404
            );
        }

        if (
            !in_array(
                $reporte->repop_estado,
                ['ENVIADO', 'RECIBIDO'],
                true
            )
        ) {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'EL CONSOLIDADO NO SE ENCUENTRA EN UN ESTADO VÁLIDO PARA SU RECEPCIÓN',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        try {
            DB::transaction(
                function () use ($reporte, $user) {
                    if ($reporte->repop_estado === 'ENVIADO') {
                        $reporte->repop_estado = 'RECIBIDO';
                        $reporte->repop_fecha_recepcion = now();
                        $reporte->repop_user_destino = $user->id;
                        $reporte->repop_usuamod = $user->id;
                        $reporte->repop_fechamod = now();
                        $reporte->save();
                    }

                    $this->marcarNotificacionesLeidas(
                        $reporte->repop_cod,
                        $user->id
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'CONSOLIDADO RECIBIDO CORRECTAMENTE',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO REGISTRAR LA RECEPCIÓN DEL CONSOLIDADO',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | DPTO. III - OBSERVAR CONSOLIDADO
    |--------------------------------------------------------------------------
    | RECIBIDO -> OBSERVADO
    */
    public function observarConsolidadoAdmin(
        Request $request,
        string $id
    ) {
        if (!$this->esRol('Super-Admin', 'Admin-Dpto-III')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL ADMINISTRADOR DEL DPTO. III PUEDE OBSERVAR CONSOLIDADOS',
                ],
                403
            );
        }

        $validator = Validator::make(
            $request->all(),
            [
                'observacion' => [
                    'required',
                    'string',
                    'min:5',
                    'max:2000',
                ],
            ]
        );

        if ($validator->fails()) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'DEBE REGISTRAR UNA OBSERVACIÓN VÁLIDA',
                    'errors' => $validator->errors(),
                ],
                422
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'DIVISION')
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL CONSOLIDADO NO EXISTE',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'RECIBIDO') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN OBSERVAR CONSOLIDADOS EN ESTADO RECIBIDO',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        $g3 = User::find($reporte->repop_user_emisor);

        if (!$g3) {
            return response()->json(
                [
                    'message' => 422,
                    'message_text' =>
                    'NO SE ENCONTRÓ AL G-3 EMISOR DEL CONSOLIDADO',
                ],
                422
            );
        }

        $observacion = trim($request->observacion);

        try {
            DB::transaction(
                function () use (
                    $reporte,
                    $user,
                    $g3,
                    $observacion
                ) {
                    $reporte->repop_estado = 'OBSERVADO';
                    $reporte->repop_observacion = $observacion;
                    $reporte->repop_fecha_revision = now();
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    $this->crearNotificacion(
                        [
                            'notif_repop_cod' => $reporte->repop_cod,
                            'notif_tipo' => 'REPORTE_DIVISION_OBSERVADO',
                            'notif_titulo' =>
                            'CONSOLIDADO OBSERVADO POR EL DPTO. III',
                            'notif_mensaje' =>
                            'El consolidado fue observado por el Administrador del Dpto. III. Motivo: ' .
                                $observacion,
                            'notif_user_emisor' => $user->id,
                            'notif_user_destino' => $g3->id,
                            'notif_prioridad' => 'IMPORTANTE',
                            'notif_ruta' =>
                            '/reportes-operativos/' .
                                $reporte->repop_cod,
                            'notif_datos' => [
                                'reporte_id' => $reporte->repop_cod,
                                'observacion' => $observacion,
                                'estado' => 'OBSERVADO',
                            ],
                            'notif_usuareg' => $user->id,
                        ]
                    );
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'CONSOLIDADO OBSERVADO CORRECTAMENTE. EL G-3 FUE NOTIFICADO.',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO OBSERVAR EL CONSOLIDADO',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |--------------------------------------------------------------------------
    | DPTO. III - APROBAR CONSOLIDADO
    |--------------------------------------------------------------------------
    | RECIBIDO -> APROBADO
    */
    public function aprobarConsolidadoAdmin(string $id)
    {
        if (!$this->esRol('Super-Admin', 'Admin-Dpto-III')) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'SOLO EL ADMINISTRADOR DEL DPTO. III PUEDE APROBAR CONSOLIDADOS',
                ],
                403
            );
        }

        $user = auth()->user();

        $reporte = ReporteOperativo::where(
            'repop_cod',
            $id
        )
            ->where('repop_tipo', 'DIVISION')
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL CONSOLIDADO NO EXISTE',
                ],
                404
            );
        }

        if ($reporte->repop_estado !== 'RECIBIDO') {
            return response()->json(
                [
                    'message' => 409,
                    'message_text' =>
                    'SOLO SE PUEDEN APROBAR CONSOLIDADOS EN ESTADO RECIBIDO',
                    'estado_actual' => $reporte->repop_estado,
                ],
                409
            );
        }

        /*
|--------------------------------------------------------------------------
| ÚLTIMA VALIDACIÓN DE INTEGRIDAD
|--------------------------------------------------------------------------
|
| El Dpto. III jamás puede aprobar un consolidado incompleto
| o desactualizado.
|
*/
        $integridad =
            $this->validarIntegridadConsolidado(
                $reporte
            );


        if (!$integridad['ok']) {

            return response()->json(
                [
                    'message' => 409,

                    'message_text' =>
                    $integridad['message'],

                    'tipo' =>
                    $integridad['tipo']
                        ?? 'CONSOLIDADO_INCOMPLETO',

                    'control' =>
                    $integridad['control']
                        ?? null,
                ],
                409
            );
        }

        $g3 = User::find($reporte->repop_user_emisor);

        try {
            DB::transaction(
                function () use ($reporte, $user, $g3) {
                    $reporte->repop_estado = 'APROBADO';
                    $reporte->repop_observacion = null;
                    $reporte->repop_fecha_revision = now();
                    $reporte->repop_usuamod = $user->id;
                    $reporte->repop_fechamod = now();
                    $reporte->save();

                    if ($g3) {
                        $this->crearNotificacion(
                            [
                                'notif_repop_cod' => $reporte->repop_cod,
                                'notif_tipo' => 'CONSOLIDADO_APROBADO',
                                'notif_titulo' =>
                                'CONSOLIDADO APROBADO POR EL DPTO. III',
                                'notif_mensaje' =>
                                'El consolidado de la División fue aprobado por el Administrador del Dpto. III.',
                                'notif_user_emisor' => $user->id,
                                'notif_user_destino' => $g3->id,
                                'notif_prioridad' => 'NORMAL',
                                'notif_ruta' =>
                                '/reportes-operativos/' .
                                    $reporte->repop_cod,
                                'notif_datos' => [
                                    'reporte_id' => $reporte->repop_cod,
                                    'estado' => 'APROBADO',
                                ],
                                'notif_usuareg' => $user->id,
                            ]
                        );
                    }
                }
            );

            $reporte->refresh();

            return response()->json(
                [
                    'message' => 200,
                    'message_text' =>
                    'CONSOLIDADO APROBADO CORRECTAMENTE POR EL DPTO. III',
                    'reporte' => $this->reporteFrontend($reporte),
                ]
            );
        } catch (\Throwable $e) {
            return response()->json(
                [
                    'message' => 500,
                    'message_text' =>
                    'NO SE PUDO APROBAR EL CONSOLIDADO',
                    'error' => $e->getMessage(),
                ],
                500
            );
        }
    }

    /*
    |==========================================================================
    | DETALLE GENERAL DEL REPORTE (P-3 / G-3 / DPTO. III)
    |==========================================================================
    */
    public function verReporteOperativo(string $id)
    {
        $user = auth()->user();

        if (!$user) {
            return response()->json(
                [
                    'message' => 401,
                    'message_text' => 'USUARIO NO AUTENTICADO',
                ],
                401
            );
        }

        $reporte = ReporteOperativo::with([
            'detalles',
            'unidad',
            'emisor',
        ])
            ->where('repop_cod', $id)
            ->where('repop_activo', 'A')
            ->first();

        if (!$reporte) {
            return response()->json(
                [
                    'message' => 404,
                    'message_text' =>
                    'EL REPORTE OPERATIVO NO EXISTE',
                ],
                404
            );
        }

        $roles = $this->rolesUsuario($user);

        $esAdmin = collect($roles)->contains(
            fn($role) => in_array(
                $role,
                ['Super-Admin', 'Admin-Dpto-III'],
                true
            )
        );

        $esG3 = in_array('G-3', $roles, true);
        $esP3 = in_array('P-3', $roles, true);

        $puedeVer = $esAdmin;

        if ($esG3) {
            $puedeVer =
                (string) $reporte->repop_div_cod ===
                (string) $user->user_uni_cod;
        }

        if ($esP3) {
            $puedeVer =
                (string) $reporte->repop_uni_cod ===
                (string) $user->user_uni_cod
                ||
                (string) $reporte->repop_user_emisor ===
                (string) $user->id;
        }

        if (!$puedeVer) {
            return response()->json(
                [
                    'message' => 403,
                    'message_text' =>
                    'NO TIENE PERMISO PARA VER ESTE REPORTE',
                ],
                403
            );
        }

        $division = Unidade::select(
            'uni_cod',
            'uni_detalle',
            'uni_abrev'
        )
            ->where(
                'uni_cod',
                $reporte->repop_div_cod
            )
            ->first();

        $unidadesFuente = collect();

        if ($reporte->repop_tipo === 'DIVISION') {
            $unidadesFuente = ReporteOperativoFuente::with([
                'reporteFuente.unidad',
            ])
                ->where(
                    'rofue_reporte_destino',
                    $reporte->repop_cod
                )
                ->where(
                    'rofue_estado',
                    'A'
                )
                ->orderBy('rofue_orden')
                ->get()
                ->map(
                    function ($fuente) {
                        $reporteFuente = $fuente->reporteFuente;
                        $unidad = $reporteFuente?->unidad;

                        if (!$reporteFuente || !$unidad) {
                            return null;
                        }

                        return [
                            'reporte_cod' =>
                            $reporteFuente->repop_cod,
                            'uni_cod' => $unidad->uni_cod,
                            'uni_detalle' => $unidad->uni_detalle,
                            'uni_abrev' => $unidad->uni_abrev,
                        ];
                    }
                )
                ->filter()
                ->unique('uni_cod')
                ->values();
        }

        $unidadesPorCodigo = Unidade::select(
            'uni_cod',
            'uni_detalle',
            'uni_abrev'
        )
            ->whereIn(
                'uni_cod',
                $reporte->detalles
                    ->pluck('rodet_uni_cod')
                    ->filter()
                    ->unique()
                    ->values()
            )
            ->get()
            ->keyBy('uni_cod');

        $detalles = $reporte->detalles
            ->map(
                function ($detalle) use (
                    $unidadesPorCodigo,
                    $division
                ) {
                    $unidadDetalle = $unidadesPorCodigo->get(
                        $detalle->rodet_uni_cod
                    );

                    return [
                        'rodet_cod' => $detalle->rodet_cod,
                        'division_cod' => $detalle->rodet_div_cod,
                        'division' =>
                        $detalle->rodet_division
                            ?? $division?->uni_detalle,
                        'division_abrev' =>
                        $detalle->rodet_division_abrev
                            ?? $division?->uni_abrev,
                        'unidad_cod' => $detalle->rodet_uni_cod,
                        'unidad' =>
                        $detalle->rodet_unidad
                            ?? $unidadDetalle?->uni_detalle,
                        'unidad_abrev' =>
                        $detalle->rodet_unidad_abrev
                            ?? $unidadDetalle?->uni_abrev,
                        'puesto_cod' => $detalle->rodet_puesto_cod,
                        'puesto' => $detalle->rodet_puesto,
                        'puesto_tipo' => $detalle->rodet_puesto_tipo,
                        'mision_cod' => $detalle->rodet_mision_cod,
                        'mision' => $detalle->rodet_mision,
                        'mision_nro' => $detalle->rodet_mision_nro,
                        'mision_fecha' => $detalle->rodet_mision_fecha,
                        'mision_fechafin' =>
                        $detalle->rodet_mision_fechafin,
                        'per_cod' => $detalle->rodet_per_cod,
                        'user_id' => $detalle->rodet_user_id,
                        'personal' => $detalle->rodet_personal,
                        'grado' => $detalle->rodet_grado,
                        'especialidad' =>
                        $detalle->rodet_especialidad,
                        'ci' => $detalle->rodet_ci,
                        'codigo_identificacion' =>
                        $detalle->rodet_codigo_identificacion,
                        'fecha_inicio' => $detalle->rodet_fecha_inicio,
                        'fecha_fin' => $detalle->rodet_fecha_fin,
                        'estado' => $detalle->rodet_estado,
                        'observacion' =>
                        $detalle->rodet_observacion,
                    ];
                }
            );

        $puestos = $detalles
            ->groupBy(
                function ($detalle) {
                    return ($detalle['unidad_cod'] ?? 'SIN_UNIDAD') .
                        '-' .
                        ($detalle['puesto_cod'] ?? 'SIN_PUESTO');
                }
            )
            ->map(
                function ($items) {
                    $primero = $items->first();

                    return [
                        'puesto_cod' => $primero['puesto_cod'],
                        'puesto' => $primero['puesto'],
                        'puesto_tipo' => $primero['puesto_tipo'],
                        'unidad_cod' => $primero['unidad_cod'],
                        'unidad' => $primero['unidad'],
                        'unidad_abrev' => $primero['unidad_abrev'],
                        'total_personal' => $items
                            ->pluck('user_id')
                            ->filter()
                            ->unique()
                            ->count(),
                        'personal' => $items->values(),
                    ];
                }
            )
            ->values();

        $tipoNotificacionObservacion =
            $reporte->repop_tipo === 'DIVISION'
            ? 'REPORTE_DIVISION_OBSERVADO'
            : 'REPORTE_OBSERVADO';

        $notificacionesObservacion =
            NotificacionOperativa::with([
                'emisor:id,name',
            ])
            ->where(
                'notif_repop_cod',
                $reporte->repop_cod
            )
            ->where(
                'notif_tipo',
                $tipoNotificacionObservacion
            )
            ->where(
                'notif_activo',
                'A'
            )
            ->orderByDesc('notif_fechareg')
            ->orderByDesc('notif_cod')
            ->get();

        $historialObservaciones =
            $notificacionesObservacion
            ->values()
            ->map(
                function (
                    $notificacion,
                    $indice
                ) use ($reporte) {
                    $datos = is_array(
                        $notificacion->notif_datos
                    )
                        ? $notificacion->notif_datos
                        : [];

                    $observacion = trim(
                        (string) (
                            $datos['observacion'] ?? ''
                        )
                    );

                    if ($observacion === '') {
                        $observacion =
                            $notificacion->notif_mensaje
                            ?? 'Observación no disponible';
                    }

                    $esPendiente =
                        $indice === 0
                        && $reporte->repop_estado === 'OBSERVADO'
                        && !empty($reporte->repop_observacion);

                    return [
                        'notif_cod' =>
                        $notificacion->notif_cod,
                        'fecha' =>
                        $notificacion->notif_fechareg,
                        'emisor_id' =>
                        $notificacion->notif_user_emisor,
                        'emisor' =>
                        $notificacion->emisor?->name
                            ?? 'Usuario',
                        'observacion' => $observacion,
                        'estado_observacion' =>
                        $esPendiente
                            ? 'PENDIENTE'
                            : 'ATENDIDA',
                        'estado_notificacion' =>
                        $notificacion->notif_estado,
                        'fecha_lectura' =>
                        $notificacion->notif_fecha_lectura,
                        'prioridad' =>
                        $notificacion->notif_prioridad,
                    ];
                }
            )
            ->values();

        return response()->json(
            [
                'message' => 200,
                'message_text' =>
                'REPORTE OPERATIVO OBTENIDO CORRECTAMENTE',
                'reporte' => $this->reporteFrontend($reporte),
                'division' => $division,
                'unidad' => $reporte->unidad
                    ? [
                        'uni_cod' => $reporte->unidad->uni_cod,
                        'uni_detalle' =>
                        $reporte->unidad->uni_detalle,
                        'uni_abrev' =>
                        $reporte->unidad->uni_abrev,
                    ]
                    : null,
                'unidades_fuente' => $unidadesFuente,
                'emisor' => $reporte->emisor
                    ? [
                        'id' => $reporte->emisor->id,
                        'name' => $reporte->emisor->name,
                    ]
                    : null,
                'totales' => [
                    'puestos' => $puestos->count(),
                    'personal' => $detalles
                        ->pluck('user_id')
                        ->filter()
                        ->unique()
                        ->count(),
                    'registros' => $detalles->count(),
                ],
                'puestos' => $puestos,
                'detalles' => $detalles->values(),
                'historial_observaciones' =>
                $historialObservaciones,
            ]
        );
    }
}
