<?php
/**
 * ActividadAdmin — Trazabilidad del módulo administrativo de laboratorio
 * Registra toda acción realizada sobre las entidades del módulo.
 */

require_once __DIR__ . '/../../classes/Database.php';

class ActividadAdmin {

    private Database $db;

    public function __construct() {
        $this->db = Database::getInstance();
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Registro de actividad
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Registra una acción en el log.
     *
     * @param int|null $adminId      admin_users.id
     * @param string   $modulo       pacientes|ordenes|domicilios|enfermeras|asignaciones
     * @param string   $accion       crear|editar|eliminar|autorizar|rechazar|asignar...
     * @param int|null $entidadId    ID del registro afectado
     * @param mixed    $detalle      Texto o array (se serializa como JSON)
     */
    public function registrar(
        ?int $adminId,
        string $modulo,
        string $accion,
        ?int $entidadId = null,
        $detalle = null
    ): int {
        $adminNombre = null;

        if ($adminId) {
            $row = $this->db->fetch(
                'SELECT full_name FROM admin_users WHERE id = ?',
                [$adminId]
            );
            $adminNombre = $row['full_name'] ?? null;
        }

        $detalleStr = is_array($detalle) || is_object($detalle)
            ? json_encode($detalle, JSON_UNESCAPED_UNICODE)
            : (string)($detalle ?? '');

        // Resolver IP real del cliente (detrás de proxy/Coolify/Nginx)
        $ip = null;
        foreach (['HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','HTTP_CF_CONNECTING_IP','REMOTE_ADDR'] as $h) {
            if (!empty($_SERVER[$h])) {
                $ip = trim(explode(',', $_SERVER[$h])[0]);
                break;
            }
        }

        return $this->db->insert('lab_actividad_admin', [
            'admin_id'    => $adminId,
            'admin_nombre'=> $adminNombre,
            'modulo'      => $modulo,
            'accion'      => $accion,
            'entidad_id'  => $entidadId,
            'detalle'     => $detalleStr,
            'ip_address'  => $ip,
            'user_agent'  => $_SERVER['HTTP_USER_AGENT'] ?? null,
        ]);
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Consultas
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Actividad reciente del módulo.
     *
     * @param int    $limit
     * @param string $modulo  Filtro opcional por módulo
     */
    public function reciente(int $limit = 50, string $modulo = ''): array {
        $where = $modulo ? 'WHERE a.modulo = ?' : '';
        $params = $modulo ? [$modulo] : [];
        $params[] = $limit;

        return $this->db->fetchAll("
            SELECT
                a.*,
                u.username AS admin_username
            FROM  lab_actividad_admin a
            LEFT  JOIN admin_users u ON u.id = a.admin_id
            $where
            ORDER BY a.created_at DESC
            LIMIT ?
        ", $params);
    }

    /**
     * Actividad de un administrador específico.
     */
    public function porAdmin(int $adminId, int $limit = 100): array {
        return $this->db->fetchAll("
            SELECT * FROM lab_actividad_admin
            WHERE admin_id = ?
            ORDER BY created_at DESC
            LIMIT ?
        ", [$adminId, $limit]);
    }

    /**
     * Actividad sobre una entidad concreta.
     */
    public function porEntidad(string $modulo, int $entidadId): array {
        return $this->db->fetchAll("
            SELECT
                a.*,
                u.username AS admin_username
            FROM  lab_actividad_admin a
            LEFT  JOIN admin_users u ON u.id = a.admin_id
            WHERE a.modulo = ? AND a.entidad_id = ?
            ORDER BY a.created_at ASC
        ", [$modulo, $entidadId]);
    }

    /**
     * Estadísticas de actividad por módulo en un rango de fechas.
     */
    public function estadisticas(string $desde, string $hasta): array {
        return $this->db->fetchAll("
            SELECT
                modulo,
                accion,
                COUNT(*) AS total
            FROM  lab_actividad_admin
            WHERE DATE(created_at) BETWEEN ? AND ?
            GROUP BY modulo, accion
            ORDER BY modulo, total DESC
        ", [$desde, $hasta]);
    }

    /**
     * Filtrado avanzado con paginación.
     *
     * @param array $opts {desde, hasta, modulo, accion, admin_id, buscar, page, per_page}
     * @return array      {data, total, paginas, pagina}
     */
    public function filtrar(array $opts = []): array {
        $where  = [];
        $params = [];

        if (!empty($opts['desde'])) {
            $where[]  = 'DATE(a.created_at) >= ?';
            $params[] = $opts['desde'];
        }
        if (!empty($opts['hasta'])) {
            $where[]  = 'DATE(a.created_at) <= ?';
            $params[] = $opts['hasta'];
        }
        if (!empty($opts['modulo'])) {
            $where[]  = 'a.modulo = ?';
            $params[] = $opts['modulo'];
        }
        if (!empty($opts['accion'])) {
            $where[]  = 'a.accion = ?';
            $params[] = $opts['accion'];
        }
        if (!empty($opts['admin_id'])) {
            $where[]  = 'a.admin_id = ?';
            $params[] = (int)$opts['admin_id'];
        }
        if (!empty($opts['buscar'])) {
            $where[]  = '(a.admin_nombre LIKE ? OR a.detalle LIKE ?)';
            $like     = '%' . $opts['buscar'] . '%';
            $params[] = $like;
            $params[] = $like;
        }

        $whereStr = $where ? 'WHERE ' . implode(' AND ', $where) : '';

        $total = (int)($this->db->fetch(
            "SELECT COUNT(*) AS n FROM lab_actividad_admin a $whereStr",
            $params
        )['n'] ?? 0);

        $pp  = max(1, (int)($opts['per_page'] ?? 50));
        $pag = max(1, (int)($opts['page']     ?? 1));
        $off = ($pag - 1) * $pp;

        $pParams   = $params;
        $pParams[] = $pp;
        $pParams[] = $off;

        $data = $this->db->fetchAll("
            SELECT
                a.*,
                u.username AS admin_username
            FROM  lab_actividad_admin a
            LEFT  JOIN admin_users u ON u.id = a.admin_id
            $whereStr
            ORDER BY a.created_at DESC
            LIMIT ? OFFSET ?
        ", $pParams);

        return [
            'data'    => $data,
            'total'   => $total,
            'paginas' => (int)ceil($total / $pp),
            'pagina'  => $pag,
        ];
    }
}
