<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AuditoriaLog;
use App\Models\Admin\Sede;
use App\Models\User;
use App\Support\Pdf\SimplePdf;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;

class AuditoriaController extends Controller
{
    /**
     * Construye el query base (con filtros) para auditoría.
     */
    private function buildQuery(Request $request)
    {
        $idSede = $request->input('id_sede');
        $userId = $request->input('user_id');
        $from = $request->input('from');
        $to = $request->input('to');
        $action = $request->input('action');

        $q = AuditoriaLog::query()->with(['user.tipoUsuario', 'user.sede']);

        if (!empty($idSede)) {
            $q->where('id_sede', $idSede);
        }
        if (!empty($userId)) {
            $q->where('user_id', $userId);
        }
        if (!empty($action)) {
            $q->where('action', $action);
        }

        if (!empty($from)) {
            $fromDt = Carbon::parse($from)->startOfDay();
            $q->where('created_at', '>=', $fromDt);
        }
        if (!empty($to)) {
            $toDt = Carbon::parse($to)->endOfDay();
            $q->where('created_at', '<=', $toDt);
        }

        return $q;
    }

    public function index(Request $request)
    {
        if (!Schema::hasTable('auditoria_logs')) {
            return view('Admin.auditoria.index', [
                'sedes' => collect(),
                'users' => collect(),
                'logs' => new \Illuminate\Pagination\LengthAwarePaginator([], 0, 50),
                'idSede' => null,
                'userId' => null,
                'from' => null,
                'to' => null,
                'action' => null,
                'group' => null,
                'acciones' => collect(),
                'audit_not_ready' => true,
            ]);
        }

        $sedes = Sede::noEliminados()->orderBy('sede')->get();

        $idSede = $request->input('id_sede');
        $userId = $request->input('user_id');
        $from = $request->input('from');
        $to = $request->input('to');
        $action = $request->input('action');
        $group = $request->input('group');

        // Lista de usuarios (opcionalmente filtrada por sede)
        $usersQ = User::noEliminados()->with(['sede', 'tipoUsuario'])->orderBy('nombres');
        if (!empty($idSede)) {
            $usersQ->where('id_sede', $idSede);
        }
        $users = $usersQ->get();

        $q = $this->buildQuery($request);
        $logs = $q->orderByDesc('created_at')->paginate(50)->appends($request->query());

        // Para dropdown de acciones comunes
        $acciones = AuditoriaLog::query()
            ->select('action')
            ->whereNotNull('action')
            ->groupBy('action')
            ->orderBy('action')
            ->pluck('action');

        return view('Admin.auditoria.index', compact('sedes', 'users', 'logs', 'idSede', 'userId', 'from', 'to', 'action', 'acciones', 'group'));
    }

    /**
     * Vista agrupada por usuario (misma data, distinta presentación).
     */
    public function grouped(Request $request)
    {
        if (!Schema::hasTable('auditoria_logs')) {
            abort(404);
        }

        $sedes = Sede::noEliminados()->orderBy('sede')->get();

        $idSede = $request->input('id_sede');
        $userId = $request->input('user_id');
        $from = $request->input('from');
        $to = $request->input('to');
        $action = $request->input('action');

        $usersQ = User::noEliminados()->with(['sede', 'tipoUsuario'])->orderBy('nombres');
        if (!empty($idSede)) {
            $usersQ->where('id_sede', $idSede);
        }
        $users = $usersQ->get();

        $q = $this->buildQuery($request);

        // Para la vista agrupada, traemos un volumen razonable. Si necesitas más,
        // normalmente se usa exportación (CSV/PDF).
        $logs = $q->orderBy('user_id')->orderBy('created_at')->limit(5000)->get();

        $grouped = $logs->groupBy(function (AuditoriaLog $log) {
            $u = $log->user;
            $nombre = '—';
            if ($u) {
                if (!empty($u->nombre_completo)) {
                    $nombre = $u->nombre_completo;
                } elseif (!empty($u->name)) {
                    $nombre = $u->name;
                }
            }
            $dni = $u ? $u->dni : null;
            return trim(($dni ? $dni.' - ' : '').$nombre);
        });

        $acciones = AuditoriaLog::query()
            ->select('action')
            ->whereNotNull('action')
            ->groupBy('action')
            ->orderBy('action')
            ->pluck('action');

        return view('Admin.auditoria.grouped', compact('sedes', 'users', 'idSede', 'userId', 'from', 'to', 'action', 'acciones', 'grouped'));
    }

    /**
     * Exporta auditoría a CSV (Excel compatible).
     */
    public function exportCsv(Request $request)
    {
        if (!Schema::hasTable('auditoria_logs')) {
            abort(404);
        }

        $q = $this->buildQuery($request)->orderBy('created_at');

        $now = now()->format('Ymd_His');
        $filename = "auditoria_{$now}.csv";

        $headers = [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ];

        return response()->streamDownload(function () use ($q) {
            $out = fopen('php://output', 'w');

            // BOM para Excel (UTF-8)
            fwrite($out, "\xEF\xBB\xBF");

            fputcsv($out, [
                'Fecha',
                'Hora',
                'Sede',
                'Usuario',
                'Tipo Usuario',
                'Módulo',
                'Acción',
                'Detalle',
                'IP',
                'Método',
                'Status',
                'Ruta',
                'URL',
                'Payload',
            ]);

            $q->chunk(1000, function ($logs) use ($out) {
                foreach ($logs as $log) {
                    /** @var \App\Models\AuditoriaLog $log */
                    $u = $log->user;
                    $nombre = '—';
                    if ($u) {
                        if (!empty($u->nombre_completo)) {
                            $nombre = $u->nombre_completo;
                        } elseif (!empty($u->name)) {
                            $nombre = $u->name;
                        }
                    }
                    $dni = $u ? $u->dni : null;
                    $usuario = trim(($dni ? $dni.' - ' : '').$nombre);

                    $payloadTxt = $log->payload ? json_encode($log->payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : '';

                    $fecha = $log->created_at ? $log->created_at->format('d/m/Y') : '';
                    $hora = $log->created_at ? $log->created_at->format('H:i:s') : '';

                    fputcsv($out, [
                        $fecha,
                        $hora,
                        $log->sede_nome,
                        $usuario,
                        $log->tipo_usuario_nombre,
                        (string) ($log->module ? $log->module : ''),
                        (string) ($log->action ? $log->action : ''),
                        (string) ($log->description ? $log->description : ''),
                        (string) ($log->ip_address ? $log->ip_address : ''),
                        (string) ($log->method ? $log->method : ''),
                        (string) ($log->status_code ? $log->status_code : ''),
                        (string) ($log->route_name ? $log->route_name : ''),
                        (string) ($log->url ? $log->url : ''),
                        $payloadTxt,
                    ]);
                }
            });

            fclose($out);
        }, $filename, $headers);
    }

    /**
     * Exporta auditoría a PDF (sin dependencias externas), agrupada por usuario.
     */
    public function exportPdf(Request $request)
    {
        if (!Schema::hasTable('auditoria_logs')) {
            abort(404);
        }

        $q = $this->buildQuery($request)->orderBy('user_id')->orderBy('created_at');

        $filters = collect([
            $request->filled('id_sede') ? ('Sede ID: '.$request->input('id_sede')) : null,
            $request->filled('user_id') ? ('Usuario ID: '.$request->input('user_id')) : null,
            $request->filled('action') ? ('Acción: '.$request->input('action')) : null,
            $request->filled('from') ? ('Desde: '.$request->input('from')) : null,
            $request->filled('to') ? ('Hasta: '.$request->input('to')) : null,
        ])->filter()->values()->implode(' | ');

        $title = 'Reporte de Auditoría';
        $subtitle = $filters ? $filters : 'Sin filtros';

        $pdf = new SimplePdf('L'); // A4 horizontal

        $lines = [];
        $lines[] = $title;
        $lines[] = $subtitle;
        $lines[] = 'Generado: '.now()->format('d/m/Y H:i:s');
        $lines[] = str_repeat('-', 160);

        $currentUserKey = null;

        $pushPageIfNeeded = function () use (&$pdf, &$lines) {
            // 47 líneas aprox en A4 horizontal con fuente 9-10.
            if (count($lines) >= 48) {
                $pdf->addPage($lines);
                $lines = [];
            }
        };

        $q->chunk(800, function ($chunk) use (&$lines, &$currentUserKey, $pushPageIfNeeded) {
            foreach ($chunk as $log) {
                /** @var \App\Models\AuditoriaLog $log */
                $u = $log->user;
                $nombre = '—';
                if ($u) {
                    if (!empty($u->nombre_completo)) {
                        $nombre = $u->nombre_completo;
                    } elseif (!empty($u->name)) {
                        $nombre = $u->name;
                    }
                }
                $dni = $u ? $u->dni : null;
                $usuario = trim(($dni ? $dni.' - ' : '').$nombre);
                $key = $usuario.'|'.$log->tipo_usuario_nombre.'|'.$log->sede_nombre;

                if ($currentUserKey !== $key) {
                    $currentUserKey = $key;
                    $lines[] = '';
                    $lines[] = 'Usuario: '.$usuario;
                    $lines[] = 'Tipo: '.$log->tipo_usuario_nombre.' | Sede: '.$log->sede_nombre;
                    $lines[] = str_repeat('-', 160);
                    $lines[] = 'Fecha Hora     | Módulo                 | Acción        | Detalle';
                    $lines[] = str_repeat('-', 160);
                }

                $fechaHora = $log->created_at ? $log->created_at->format('d/m/Y H:i:s') : '';
                $mod = (string) (isset($log->module) ? $log->module : '-');
                $act = (string) (isset($log->action) ? $log->action : '-');
                $det = (string) (isset($log->description) ? $log->description : '-');

                // Normaliza espacios y recorta para tabla fija
                $mod = Str::limit(preg_replace('/\s+/', ' ', $mod), 22, '…');
                $act = Str::limit(preg_replace('/\s+/', ' ', $act), 12, '…');
                $det = preg_replace('/\s+/', ' ', $det);
                $det = Str::limit($det, 95, '…');

                $lines[] = sprintf('%-16s | %-22s | %-12s | %s', $fechaHora, $mod, $act, $det);

                $pushPageIfNeeded();
            }
        });

        if (!empty($lines)) {
            $pdf->addPage($lines);
        }

        $bin = $pdf->output();

        $now = now()->format('Ymd_His');
        $filename = "auditoria_{$now}.pdf";

        return response($bin, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
        ]);
    }
}
