<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;

class ViaticosController extends Controller
{
    // 1) LISTA DE TAREAS (query base + filtros opcionales región/departamento/municipio)
    public function tareas(Request $request)
    {
        $operadorId   = Auth::id();
        $regionId     = $request->get('region_id');
        $departamento = $request->get('departamento');
        $municipio    = $request->get('municipio');

        $sql = <<<SQL
;WITH ult_evento AS (
    SELECT 
        ev.radicado,
        MAX(ev.id_solicitudes) AS id_ultimo_evento
    FROM gestion_terceros.dbo.evento_solicitudes ev
    GROUP BY ev.radicado
)
SELECT DISTINCT
    s.rad_via AS radicado,
    s.numero_identificacion_titular AS cedula,
    e.fecha_solicitud,
    r.descripcion AS regiona,
    m.descripcion_dep AS departamento,
    m.descripcion_mun AS municipio,
    s.url_drive AS url_drive
FROM solicitudes s
JOIN afiliado a 
    ON s.numero_identificacion_titular = a.numero_documento
JOIN municipio m 
    ON a.codigo_dane_municipio_atencion = m.id
JOIN region r 
    ON m.region_id = r.id
JOIN lote l 
    ON r.lote_id = l.id
LEFT JOIN ult_evento ue 
    ON LTRIM(RTRIM(ue.radicado)) = LTRIM(RTRIM(CAST(s.radicado AS VARCHAR(50))))
LEFT JOIN gestion_terceros.dbo.evento_solicitudes e 
    ON e.id_solicitudes = ue.id_ultimo_evento
WHERE s.proceso_tercero = 'viaticos'
  AND s.proceso = 'Aprobado'
  AND EXISTS (
        SELECT 1
        FROM operador_lote ol
        WHERE ol.operador_id = :operadorId1 
          AND ol.lote_id = r.lote_id
  )
SQL;

        $params = ['operadorId1' => $operadorId];
        if (!empty($regionId)) {
            $sql .= " AND r.id = :region_id";
            $params['region_id'] = $regionId;
        }
        if (!empty($departamento)) {
            $sql .= " AND m.descripcion_dep = :departamento";
            $params['departamento'] = $departamento;
        }
        if (!empty($municipio)) {
            $sql .= " AND m.descripcion_mun = :municipio";
            $params['municipio'] = $municipio;
        }

        $sql .= " ORDER BY e.fecha_solicitud DESC";

        $tareas = DB::select($sql, $params);

        return view('viaticos.tareas', [
            'tareas'  => $tareas,
            'filtros' => $request->all(),
        ]);
    }

    // 2) ACCIONES (AJAX): Reembolso pagado, Evento ejecutado, Subsanacion
    public function actualizarEstado(Request $request)
    {
        $request->validate([
            'radicado'    => 'required',
            'cedula'      => 'required',
            'accion'      => 'required|in:Reembolso pagado,Evento ejecutado,Subsanacion',
            'observacion' => 'nullable|string'
        ]);

        $operadorId = Auth::id();
        $radicado   = $request->radicado;
        $cedula     = $request->cedula;
        $accion     = $request->accion;

        // Observación obligatoria solo para Subsanacion
        if (in_array($accion, ['Subsanacion']) && !trim((string)$request->observacion)) {
            throw ValidationException::withMessages([
                'observacion' => 'La observación es obligatoria para esta acción.',
            ]);
        }
        // Normaliza observación: si la columna en BD es numérica, evita error de conversión
        $obs = $request->observacion;
        if ($obs !== null && !is_numeric($obs)) {
            $obs = null; // evita SQLSTATE[22018] si la columna es INT
        }

        DB::table('archivo_viaticos')->updateOrInsert(
            [
                'radicado'    => $radicado,
                'cedula'      => $cedula,
                'operador_id' => $operadorId,
            ],
            [
                'region_id'   => DB::raw("(SELECT TOP 1 r.id FROM municipio m\n                                           JOIN region r ON m.region_id = r.id\n                                           JOIN afiliado a ON a.codigo_dane_municipio_atencion = m.id\n                                           JOIN solicitudes s ON s.numero_identificacion_titular = a.numero_documento\n                                           WHERE s.rad_via = {$radicado})"),
                'estado'      => $accion,
                'observacion' => $obs,
                'fecha_subida'=> now(),
                'departamento'=> null,
                'ruta_archivo'=> null,
                'nombre_archivo'=> null,
            ]
        );

        return response()->json([
            'ok' => true,
            'allowUpload' => in_array($accion, ['Reembolso pagado','Evento ejecutado']),
            'message' => match ($accion) {
                'Reembolso pagado' => 'Reembolso pagado registrado: puedes adjuntar soportes.',
                'Evento ejecutado' => 'Evento ejecutado registrado.',
                'Subsanacion' => 'Subsanación registrada con observación.',
                default => 'Acción registrada.'
            }
        ]);
    }

    // 3) SUBIR ARCHIVOS
    public function subirArchivos(Request $request)
    {
        $request->validate([
            'cedula'       => 'required',
            'radicado'     => 'required',
            'departamento' => 'required|string',
            'archivo'      => 'required',
            'archivo.*'    => 'file',
            'estado'       => 'nullable|in:Reembolso pagado,Evento ejecutado,Subsanacion,Pendiente',
            'observacion'  => 'nullable|string'
        ]);

        $operador_id = Auth::user()->id;
        $departamento = $request->departamento;
        $rutaBase = $departamento . '/' . $request->cedula;

        foreach ($request->file('archivo') as $file) {
            $nombreOriginal = $file->getClientOriginalName();
            $path = $file->storeAs($rutaBase, now()->format('Ymd_His_') . '_' . $nombreOriginal, 'financiera');

            DB::table('archivo_viaticos')->updateOrInsert(
                [
                    'cedula'      => $request->cedula,
                    'radicado'    => $request->radicado,
                    'operador_id' => $operador_id,
                ],
                [
                    'region_id'     => DB::raw("(SELECT TOP 1 r.id FROM municipio m\n                                               JOIN region r ON m.region_id = r.id\n                                               JOIN afiliado a ON a.codigo_dane_municipio_atencion = m.id\n                                               JOIN solicitudes s ON s.numero_identificacion_titular = a.numero_documento\n                                               WHERE s.rad_via = {$request->radicado})"),
                    'ruta_archivo'  => $path,
                    'fecha_subida'  => now(),
                    'nombre_archivo'=> $nombreOriginal,
                    'departamento'  => $departamento,
                    'estado'        => $request->estado ?? 'Reembolso pagado',
                    // No guardar observación desde el flujo de subida para evitar conflictos de tipo
                ]
            );
        }

        return back()->with('success', 'Archivos subidos correctamente.');
    }

    // AJAX: regiones disponibles para el operador (según lotes y dataset)
    public function geoRegiones(Request $request)
    {
        $operadorId = Auth::id();
        $rows = DB::select(<<<SQL
SELECT DISTINCT r.id, r.descripcion
FROM solicitudes s
JOIN afiliado a ON s.numero_identificacion_titular = a.numero_documento
JOIN municipio m ON a.codigo_dane_municipio_atencion = m.id
JOIN region r ON m.region_id = r.id
JOIN lote l ON r.lote_id = l.id
WHERE s.proceso_tercero = 'viaticos'
  AND s.proceso = 'Aprobado'
  AND EXISTS (
      SELECT 1 FROM operador_lote ol
      WHERE ol.operador_id = ? AND ol.lote_id = r.lote_id
  )
ORDER BY r.descripcion
SQL
        , [$operadorId]);
        return response()->json($rows);
    }

    // AJAX: departamentos por región (limitados al operador)
    public function geoDepartamentos(Request $request)
    {
        $operadorId = Auth::id();
        $regionId = $request->query('region_id');
        if ($regionId === '' || $regionId === 'null') { $regionId = null; }
        $rows = DB::select(<<<SQL
SELECT DISTINCT m.descripcion_dep AS departamento
FROM solicitudes s
JOIN afiliado a ON s.numero_identificacion_titular = a.numero_documento
JOIN municipio m ON a.codigo_dane_municipio_atencion = m.id
JOIN region r ON m.region_id = r.id
JOIN lote l ON r.lote_id = l.id
WHERE s.proceso_tercero = 'viaticos'
  AND s.proceso = 'Aprobado'
  AND EXISTS (SELECT 1 FROM operador_lote ol WHERE ol.operador_id = ? AND ol.lote_id = r.lote_id)
  AND (? IS NULL OR r.id = ?)
ORDER BY m.descripcion_dep
SQL
        , [$operadorId, $regionId, $regionId]);
        return response()->json($rows);
    }

    // AJAX: municipios por departamento (y opcional región)
    public function geoMunicipios(Request $request)
    {
        $operadorId = Auth::id();
        $regionId = $request->query('region_id');
        if ($regionId === '' || $regionId === 'null') { $regionId = null; }
        $departamento = $request->query('departamento');
        if ($departamento === '' || $departamento === 'null') { $departamento = null; }
        $rows = DB::select(<<<SQL
SELECT DISTINCT m.descripcion_mun AS municipio
FROM solicitudes s
JOIN afiliado a ON s.numero_identificacion_titular = a.numero_documento
JOIN municipio m ON a.codigo_dane_municipio_atencion = m.id
JOIN region r ON m.region_id = r.id
JOIN lote l ON r.lote_id = l.id
WHERE s.proceso_tercero = 'viaticos'
  AND s.proceso = 'Aprobado'
  AND EXISTS (SELECT 1 FROM operador_lote ol WHERE ol.operador_id = ? AND ol.lote_id = r.lote_id)
  AND (? IS NULL OR r.id = ?)
  AND (? IS NULL OR m.descripcion_dep = ?)
ORDER BY m.descripcion_mun
SQL
        , [$operadorId, $regionId, $regionId, $departamento, $departamento]);
        return response()->json($rows);
}

    /**
     * Listar archivos existentes en una carpeta física indicada por "url_drive".
     * Espera query param "dir" codificado en base64 url-safe para evitar problemas con slashes.
     */
    public function listarArchivos(Request $request)
    {
        $encoded = $request->query('dir');
        $dir = null;
        if ($encoded) {
            // Decodificar base64 URL-safe cuando viene la ruta explícita
            $dir = base64_decode(strtr($encoded, '-_', '+/'));
            if ($dir === false || $dir === '') {
                return response()->json(['ok' => false, 'message' => 'Directorio inválido'], 400);
            }
        } else {
            // Alternativa: buscar por radicado en la BD
            $rad = $request->query('radicado');
            if (!$rad) {
                return response()->json(['ok' => false, 'message' => 'Directorio no enviado'], 400);
            }
            $row = DB::selectOne("SELECT TOP 1 url_drive FROM solicitudes WHERE rad_via = ?", [$rad]);
            if (!$row || empty($row->url_drive)) {
                return response()->json(['ok' => false, 'message' => 'No hay carpeta asociada a la solicitud'], 404);
            }
            $dir = (string) $row->url_drive;
            $encoded = rtrim(strtr(base64_encode($dir), '+/', '-_'), '=');
        }

        // Normalizar separadores y quitar trailing slash
        $dir = rtrim(str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $dir), DIRECTORY_SEPARATOR);

        // Proteger: resolver ruta real y validar que es directorio accesible
        $real = realpath($dir) ?: $dir; // en algunos discos externos realpath puede fallar si no hay permisos
        if (!is_dir($real)) {
            return response()->json(['ok' => false, 'message' => 'No se encontró el directorio de la solicitud'], 404);
        }

        $files = [];
        foreach (@scandir($real) ?: [] as $f) {
            if ($f === '.' || $f === '..') { continue; }
            $path = $real . DIRECTORY_SEPARATOR . $f;
            if (is_file($path)) {
                $files[] = [
                    'name' => $f,
                    'size' => @filesize($path) ?: 0,
                    'modified' => @date('Y-m-d H:i:s', @filemtime($path) ?: time()),
                    'preview_url' => route('viaticos.archivos.ver', [
                        'dir' => $encoded,
                        // No codificar manualmente: el generador de rutas ya codifica
                        'file' => $f,
                    ]),
                    'download_url' => route('viaticos.archivos.descargar', [
                        'dir' => $encoded,
                        // No codificar manualmente para evitar doble codificación
                        'file' => $f,
                    ]),
                ];
            }
        }

        // Ordenar por nombre
        usort($files, fn($a, $b) => strnatcasecmp($a['name'], $b['name']));

        return response()->json([
            'ok' => true,
            'dir' => $real,
            'files' => $files,
        ]);
    }

    /**
     * Visualizar archivo inline (si el navegador lo soporta)
     */
    public function verArchivo(Request $request)
    {
        $encoded = $request->query('dir');
        $file = $request->query('file');
        if (!$encoded || !$file) { abort(400, 'Faltan parámetros'); }
        $dir = base64_decode(strtr($encoded, '-_', '+/'));
        if ($dir === false) { abort(400, 'Ruta inválida'); }
        $dir = rtrim(str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $dir), DIRECTORY_SEPARATOR);
        $realDir = realpath($dir) ?: $dir;
        // Acepta valores ya codificados en % (si llegaran así)
        $safeName = basename(rawurldecode($file)); // evita traversal
        $full = $realDir . DIRECTORY_SEPARATOR . $safeName;
        if (!is_file($full)) { abort(404, 'Archivo no encontrado'); }
        // Mostrar inline si es posible (pdf, imagen, etc.)
        return response()->file($full);
    }

    /**
     * Descargar archivo forzando attachment
     */
    public function descargarArchivo(Request $request)
    {
        $encoded = $request->query('dir');
        $file = $request->query('file');
        if (!$encoded || !$file) { abort(400, 'Faltan parámetros'); }
        $dir = base64_decode(strtr($encoded, '-_', '+/'));
        if ($dir === false) { abort(400, 'Ruta inválida'); }
        $dir = rtrim(str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $dir), DIRECTORY_SEPARATOR);
        $realDir = realpath($dir) ?: $dir;
        // Acepta valores ya codificados en % (si llegaran así)
        $safeName = basename(rawurldecode($file));
        $full = $realDir . DIRECTORY_SEPARATOR . $safeName;
        if (!is_file($full)) { abort(404, 'Archivo no encontrado'); }
        return response()->download($full, $safeName);
    }
}
