<?php
/**
 * NEXUS IT — Controlador de Credenciales de Usuario
 * 
 * Permisos:
 *  - Admin/Técnico: CRUD sobre credenciales de cualquier usuario
 *  - Usuario: solo VER las suyas + EDITAR las que él mismo creó
 * 
 * Las contraseñas se cifran con AES-256-CBC y se descifran solo al momento de consultar.
 */
class CredencialController {

    // ==================== CIFRADO AES-256 ====================

    private static function getEncryptionKey(): string {
        $db = getDB();
        $stmt = $db->prepare("SELECT valor FROM configuracion WHERE clave = 'vault_encryption_key'");
        $stmt->execute();
        $key = $stmt->fetchColumn();

        // Auto-generar clave si no existe
        if (empty($key)) {
            $key = bin2hex(random_bytes(32));
            $db->prepare("UPDATE configuracion SET valor = ? WHERE clave = 'vault_encryption_key'")->execute([$key]);
        }
        return $key;
    }

    private static function encrypt(?string $plaintext): ?string {
        if ($plaintext === null || $plaintext === '') return null;
        $key = hex2bin(self::getEncryptionKey());
        $iv = random_bytes(16);
        $encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        return base64_encode($iv . $encrypted);
    }

    private static function decrypt(?string $ciphertext): ?string {
        if ($ciphertext === null || $ciphertext === '') return null;
        try {
            $key = hex2bin(self::getEncryptionKey());
            $raw = base64_decode($ciphertext);
            $iv = substr($raw, 0, 16);
            $encrypted = substr($raw, 16);
            return openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        } catch (\Exception $e) {
            return '***error***';
        }
    }

    // ==================== VERIFICAR CONTRASEÑA DEL USUARIO ====================

    public static function verificarAcceso(): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $body = Validator::getBody();
        $password = $body['password'] ?? '';

        if (empty($password)) Response::error('Contraseña requerida');

        $stmt = $db->prepare("SELECT password_hash FROM usuarios WHERE id = ?");
        $stmt->execute([$payload['sub']]);
        $user = $stmt->fetch();

        if (!$user || !password_verify($password, $user['password_hash'])) {
            Response::error('Contraseña incorrecta', 401);
        }

        Response::success(['verificado' => true], 'Acceso verificado');
    }

    // ==================== LISTAR ====================

    public static function index(): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $userId = $payload['sub'];
        $rol = $payload['rol'];

        // Admin/técnico pueden filtrar por usuario, usuario solo ve las suyas
        if ($rol === 'usuario') {
            $targetUserId = $userId;
        } else {
            $targetUserId = !empty($_GET['usuario_id']) ? (int)$_GET['usuario_id'] : null;
        }

        $where = ['1=1'];
        $params = [];

        if ($targetUserId) {
            $where[] = 'c.usuario_id = ?';
            $params[] = $targetUserId;
        }

        if (!empty($_GET['tipo'])) {
            $where[] = 'c.tipo = ?';
            $params[] = $_GET['tipo'];
        }

        $whereStr = implode(' AND ', $where);
        $sql = "SELECT c.*, u.nombre_completo as usuario_nombre, cr.nombre_completo as creador_nombre
                FROM credenciales_usuario c
                LEFT JOIN usuarios u ON c.usuario_id = u.id
                LEFT JOIN usuarios cr ON c.creado_por = cr.id
                WHERE $whereStr
                ORDER BY c.tipo, c.nombre";
        $stmt = $db->prepare($sql);
        $stmt->execute($params);
        $items = $stmt->fetchAll();

        // No descifrar aquí — solo en el endpoint /ver
        foreach ($items as &$item) {
            $item['tiene_password'] = !empty($item['password_enc']);
            $item['tiene_usuario'] = !empty($item['usuario_acceso']);
            // Descifrar usuario (es menos sensible)
            $item['usuario_acceso'] = self::decrypt($item['usuario_acceso']);
            // NO enviar password cifrado al frontend
            unset($item['password_enc']);
            // Indicar si el usuario actual puede editar
            $item['puede_editar'] = ($rol !== 'usuario') || ($item['creado_por'] == $userId);
        }

        Response::success($items);
    }

    // ==================== VER PASSWORD (requiere confirmación) ====================

    public static function verPassword(int $id): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $userId = $payload['sub'];
        $rol = $payload['rol'];

        // Obtener credencial
        $stmt = $db->prepare("SELECT * FROM credenciales_usuario WHERE id = ?");
        $stmt->execute([$id]);
        $cred = $stmt->fetch();

        if (!$cred) Response::error('Credencial no encontrada', 404);

        // Verificar acceso: usuario solo puede ver las suyas
        if ($rol === 'usuario' && $cred['usuario_id'] != $userId) {
            Response::error('No autorizado', 403);
        }

        // Descifrar y devolver
        Response::success([
            'password' => self::decrypt($cred['password_enc'])
        ]);
    }

    // ==================== CREAR ====================

    public static function crear(): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $rol = $payload['rol'];
        $userId = $payload['sub'];
        $body = Validator::getBody();

        // Determinar usuario destino
        if ($rol === 'usuario') {
            // El usuario puede crear credenciales para sí mismo
            $targetUserId = $userId;
        } else {
            // Admin/técnico especifican el usuario
            $targetUserId = (int)($body['usuario_id'] ?? 0);
            if (!$targetUserId) Response::error('usuario_id es requerido');
        }

        $nombre = trim($body['nombre'] ?? '');
        $tipo = trim($body['tipo'] ?? 'otro');
        if (empty($nombre)) Response::error('El nombre es requerido');

        $stmt = $db->prepare("INSERT INTO credenciales_usuario 
            (usuario_id, tipo, nombre, usuario_acceso, password_enc, url, notas, creado_por) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
        $stmt->execute([
            $targetUserId,
            $tipo,
            $nombre,
            self::encrypt($body['usuario_acceso'] ?? null),
            self::encrypt($body['password'] ?? null),
            $body['url'] ?? null,
            $body['notas'] ?? null,
            $userId
        ]);

        $id = (int)$db->lastInsertId();
        Response::success(['id' => $id], 'Credencial creada', 201);
    }

    // ==================== ACTUALIZAR ====================

    public static function actualizar(int $id): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $rol = $payload['rol'];
        $userId = $payload['sub'];
        $body = Validator::getBody();

        // Verificar que existe
        $stmt = $db->prepare("SELECT * FROM credenciales_usuario WHERE id = ?");
        $stmt->execute([$id]);
        $cred = $stmt->fetch();
        if (!$cred) Response::error('Credencial no encontrada', 404);

        // Permisos: usuario solo puede editar las que él creó
        if ($rol === 'usuario' && $cred['creado_por'] != $userId) {
            Response::error('Solo puedes editar credenciales que tú creaste', 403);
        }

        $fields = [];
        $params = [];

        if (isset($body['nombre'])) { $fields[] = 'nombre = ?'; $params[] = $body['nombre']; }
        if (isset($body['tipo'])) { $fields[] = 'tipo = ?'; $params[] = $body['tipo']; }
        if (isset($body['usuario_acceso'])) { $fields[] = 'usuario_acceso = ?'; $params[] = self::encrypt($body['usuario_acceso']); }
        if (isset($body['password'])) { $fields[] = 'password_enc = ?'; $params[] = self::encrypt($body['password']); }
        if (isset($body['url'])) { $fields[] = 'url = ?'; $params[] = $body['url']; }
        if (isset($body['notas'])) { $fields[] = 'notas = ?'; $params[] = $body['notas']; }

        if (empty($fields)) Response::error('Nada que actualizar');

        $params[] = $id;
        $db->prepare("UPDATE credenciales_usuario SET " . implode(', ', $fields) . " WHERE id = ?")->execute($params);

        Response::success(null, 'Credencial actualizada');
    }

    // ==================== ELIMINAR ====================

    public static function eliminar(int $id): void {
        $payload = AuthMiddleware::verificar();
        $db = getDB();
        $rol = $payload['rol'];
        $userId = $payload['sub'];

        // Solo admin/técnico pueden eliminar (o el usuario si la creó él)
        $stmt = $db->prepare("SELECT * FROM credenciales_usuario WHERE id = ?");
        $stmt->execute([$id]);
        $cred = $stmt->fetch();
        if (!$cred) Response::error('Credencial no encontrada', 404);

        if ($rol === 'usuario' && $cred['creado_por'] != $userId) {
            Response::error('No autorizado', 403);
        }

        $db->prepare("DELETE FROM credenciales_usuario WHERE id = ?")->execute([$id]);
        Response::success(null, 'Credencial eliminada');
    }
}
