<?php

namespace App\Models;

use App\Services\Database;

/**
 * Modelo User - Gestión de usuarios del sistema
 */
class User
{
    private $database;

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

    /**
     * Obtener usuario por ID
     */
    public function findById(int $id): ?array
    {
        $user = $this->database->fetchOne(
            'SELECT u.*, r.name as role_name, r.display_name as role_display_name, 
                    r.is_admin, r.permissions, r.is_active as role_active
            FROM users u 
            LEFT JOIN roles r ON u.role_id = r.id 
            WHERE u.id = ?',
            [$id]
        );
        
        if ($user) {
            // Asegurar que is_active sea boolean
            $user['is_active'] = (bool) $user['is_active'];
            $user['is_admin'] = (bool) ($user['is_admin'] ?? false);
        }
        
        return $user;
    }

    /**
     * Obtener usuario por Keycloak ID
     */
    public function findByKeycloakId(string $keycloakId): ?array
    {
        $user = $this->database->fetchOne(
            'SELECT u.*, r.name as role_name, r.display_name as role_display_name, 
                    r.is_admin, r.permissions, r.is_active as role_active
            FROM users u 
            LEFT JOIN roles r ON u.role_id = r.id 
            WHERE u.keycloak_id = ?',
            [$keycloakId]
        );
        
        if ($user) {
            // Asegurar que is_active sea boolean
            $user['is_active'] = (bool) $user['is_active'];
            $user['is_admin'] = (bool) ($user['is_admin'] ?? false);
        }
        
        return $user;
    }

    /**
     * Obtener usuario por email
     */
    public function findByEmail(string $email): ?array
    {
        return $this->database->fetchOne(
            'SELECT u.*, r.name as role_name, r.display_name as role_display_name, 
                    r.is_admin, r.permissions, r.is_active as role_active
            FROM users u 
            LEFT JOIN roles r ON u.role_id = r.id 
            WHERE u.email = ?',
            [$email]
        );
    }

    /**
     * Obtener todos los usuarios con paginación
     */
    public function getAllUsers(int $page = 1, int $perPage = 20, string $search = ''): array
    {
        $offset = ($page - 1) * $perPage;
        $searchParam = "%{$search}%";

        $whereClause = '';
        $params = [];

        if (!empty($search)) {
            $whereClause = 'WHERE u.username LIKE ? OR u.email LIKE ? OR u.first_name LIKE ? OR u.last_name LIKE ?';
            $params = [$searchParam, $searchParam, $searchParam, $searchParam];
        }

        // Obtener usuarios
        $sql = "SELECT u.*, r.name as role_name, r.display_name as role_display_name, 
                       r.is_admin, r.is_active as role_active
                FROM users u 
                LEFT JOIN roles r ON u.role_id = r.id 
                {$whereClause}
                ORDER BY u.created_at DESC 
                LIMIT {$perPage} OFFSET {$offset}";

        $users = $this->database->fetchAll($sql, $params);

        // Contar total
        $countSql = "SELECT COUNT(*) as total FROM users u {$whereClause}";
        $total = $this->database->fetchOne($countSql, $params)['total'] ?? 0;

        return [
            'users' => $users,
            'total' => $total,
            'page' => $page,
            'per_page' => $perPage,
            'total_pages' => ceil($total / $perPage)
        ];
    }

    /**
     * Obtener usuarios sin rol asignado
     */
    public function getUsersWithoutRole(): array
    {
        return $this->database->fetchAll(
            'SELECT * FROM users 
            WHERE role_id IS NULL OR is_active = FALSE 
            ORDER BY created_at ASC'
        );
    }

    /**
     * Asignar rol a usuario
     */
    public function assignRole(int $userId, int $roleId): bool
    {
        $result = $this->database->update(
            'UPDATE users SET role_id = ?, is_active = TRUE, updated_at = NOW() WHERE id = ?',
            [$roleId, $userId]
        );

        return $result > 0;
    }

    /**
     * Activar/Desactivar usuario
     */
    public function toggleUserStatus(int $userId, bool $isActive): bool
    {
        $result = $this->database->update(
            'UPDATE users SET is_active = ?, updated_at = NOW() WHERE id = ?',
            [$isActive, $userId]
        );

        return $result > 0;
    }

    /**
     * Verificar permisos del usuario
     */
    public function hasPermission(array $user, string $permission): bool
    {
        if (!$user || !$user['is_active']) {
            return false;
        }

        // Super admin tiene todos los permisos
        if ($user['role_name'] === 'super_admin') {
            return true;
        }

        // Verificar permisos específicos
        if (isset($user['permissions'])) {
            $permissions = json_decode($user['permissions'], true);
            return in_array($permission, $permissions) || in_array('all', $permissions);
        }

        return false;
    }

    /**
     * Verificar si es administrador
     */
    public function isAdmin(array $user): bool
    {
        return (bool) ($user['is_admin'] ?? false);
    }

    /**
     * Actualizar último login
     */
    public function updateLastLogin(int $userId): bool
    {
        $result = $this->database->update(
            'UPDATE users SET last_login = NOW() WHERE id = ?',
            [$userId]
        );

        return $result > 0;
    }

    /**
     * Obtener estadísticas de usuarios
     */
    public function getUserStats(): array
    {
        $totalUsers = $this->database->fetchOne('SELECT COUNT(*) as count FROM users')['count'] ?? 0;
        $activeUsers = $this->database->fetchOne('SELECT COUNT(*) as count FROM users WHERE is_active = TRUE')['count'] ?? 0;
        $usersWithoutRole = $this->database->fetchOne('SELECT COUNT(*) as count FROM users WHERE role_id IS NULL')['count'] ?? 0;
        $recentUsers = $this->database->fetchOne(
            'SELECT COUNT(*) as count FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)'
        )['count'] ?? 0;

        return [
            'total' => $totalUsers,
            'active' => $activeUsers,
            'without_role' => $usersWithoutRole,
            'recent' => $recentUsers,
            'inactive' => $totalUsers - $activeUsers
        ];
    }
}