<?php

namespace App\Models;

use App\Services\Database;

/**
 * Modelo Role - Gestión de roles y permisos del sistema
 */
class Role
{
    private $database;

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

    /**
     * Obtener todos los roles activos
     */
    public function getAllRoles(): array
    {
        return $this->database->fetchAll(
            'SELECT * FROM roles WHERE is_active = TRUE ORDER BY display_name ASC'
        );
    }

    /**
     * Obtener rol por ID
     */
    public function findById(int $id): ?array
    {
        return $this->database->fetchOne(
            'SELECT * FROM roles WHERE id = ?',
            [$id]
        );
    }

    /**
     * Obtener rol por nombre
     */
    public function findByName(string $name): ?array
    {
        return $this->database->fetchOne(
            'SELECT * FROM roles WHERE name = ?',
            [$name]
        );
    }

    /**
     * Crear nuevo rol
     */
    public function create(array $data): int
    {
        return $this->database->insert(
            'INSERT INTO roles (name, display_name, description, is_admin, permissions, is_active, created_at, updated_at) 
            VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())',
            [
                $data['name'],
                $data['display_name'],
                $data['description'] ?? null,
                $data['is_admin'] ?? false,
                isset($data['permissions']) ? json_encode($data['permissions']) : null,
                $data['is_active'] ?? true
            ]
        );
    }

    /**
     * Actualizar rol
     */
    public function update(int $id, array $data): bool
    {
        $result = $this->database->update(
            'UPDATE roles SET 
                display_name = ?, 
                description = ?, 
                is_admin = ?, 
                permissions = ?, 
                is_active = ?, 
                updated_at = NOW() 
            WHERE id = ?',
            [
                $data['display_name'],
                $data['description'] ?? null,
                $data['is_admin'] ?? false,
                isset($data['permissions']) ? json_encode($data['permissions']) : null,
                $data['is_active'] ?? true,
                $id
            ]
        );

        return $result > 0;
    }

    /**
     * Eliminar rol (solo si no tiene usuarios asignados)
     */
    public function delete(int $id): array
    {
        // Verificar si hay usuarios con este rol
        $usersWithRole = $this->database->fetchOne(
            'SELECT COUNT(*) as count FROM users WHERE role_id = ?',
            [$id]
        )['count'] ?? 0;

        if ($usersWithRole > 0) {
            return [
                'success' => false,
                'message' => 'No se puede eliminar el rol porque tiene usuarios asignados'
            ];
        }

        // Verificar que no sea un rol del sistema
        $role = $this->findById($id);
        if (!$role) {
            return [
                'success' => false,
                'message' => 'El rol no existe'
            ];
        }

        $systemRoles = ['super_admin', 'admin', 'coordinador_ti'];
        if (in_array($role['name'], $systemRoles)) {
            return [
                'success' => false,
                'message' => 'No se puede eliminar un rol del sistema'
            ];
        }

        $result = $this->database->delete('DELETE FROM roles WHERE id = ?', [$id]);

        return [
            'success' => $result > 0,
            'message' => $result > 0 ? 'Rol eliminado correctamente' : 'Error al eliminar el rol'
        ];
    }

    /**
     * Obtener usuarios por rol
     */
    public function getUsersByRole(int $roleId): array
    {
        return $this->database->fetchAll(
            'SELECT u.id, u.username, u.email, u.first_name, u.last_name, u.is_active, u.last_login
            FROM users u 
            WHERE u.role_id = ? 
            ORDER BY u.username ASC',
            [$roleId]
        );
    }

    /**
     * Obtener estadísticas de roles
     */
    public function getRoleStats(): array
    {
        $totalRoles = $this->database->fetchOne('SELECT COUNT(*) as count FROM roles WHERE is_active = TRUE')['count'] ?? 0;
        
        $roleDistribution = $this->database->fetchAll(
            'SELECT r.name, r.display_name, COUNT(u.id) as user_count 
            FROM roles r 
            LEFT JOIN users u ON r.id = u.role_id AND u.is_active = TRUE
            WHERE r.is_active = TRUE 
            GROUP BY r.id, r.name, r.display_name
            ORDER BY user_count DESC'
        );

        return [
            'total_roles' => $totalRoles,
            'distribution' => $roleDistribution
        ];
    }

    /**
     * Obtener permisos disponibles del sistema
     */
    public function getAvailablePermissions(): array
    {
        return [
            'users.manage' => 'Gestionar usuarios',
            'roles.manage' => 'Gestionar roles',
            'system.config' => 'Configuración del sistema',
            'projects.approve' => 'Aprobar proyectos',
            'projects.develop' => 'Desarrollar proyectos',
            'requirements.manage' => 'Gestionar requerimientos',
            'requirements.create' => 'Crear requerimientos',
            'processes.manage' => 'Gestionar procesos',
            'documents.manage' => 'Gestionar documentos',
            'tickets.manage' => 'Gestionar tickets',
            'tickets.create' => 'Crear tickets',
            'support.access' => 'Acceso a soporte',
            'automation.create' => 'Crear automatizaciones',
            'technical.access' => 'Acceso técnico',
            'operations.view' => 'Ver operaciones',
            'reports.view' => 'Ver reportes',
            'profile.view' => 'Ver perfil',
            'all' => 'Todos los permisos'
        ];
    }

    /**
     * Validar permisos de un rol
     */
    public function validatePermissions(array $permissions): array
    {
        $availablePermissions = array_keys($this->getAvailablePermissions());
        $validPermissions = [];
        $invalidPermissions = [];

        foreach ($permissions as $permission) {
            if (in_array($permission, $availablePermissions)) {
                $validPermissions[] = $permission;
            } else {
                $invalidPermissions[] = $permission;
            }
        }

        return [
            'valid' => $validPermissions,
            'invalid' => $invalidPermissions,
            'is_valid' => empty($invalidPermissions)
        ];
    }
}