التعديل على هذا 
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:micro_panel_lib/HomePage.dart';
import 'package:path_provider/path_provider.dart';
import 'package:router_os_client/router_os_client.dart';

void main() {
  runApp(const MicroPanelApp());
}

class MicroPanelApp extends StatelessWidget {
  const MicroPanelApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Micro Panel',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        fontFamily: 'Tajawal',
        useMaterial3: true,
      ),
      home: const SplashScreen(),
    );
  }
}

class SplashScreen extends StatefulWidget {
  const SplashScreen({super.key});

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late final Animation<double> _scaleAnimation;
  late final Animation<double> _fadeAnimation;
  late final Animation<Offset> _slideAnimation;

  @override
  void initState() {
    super.initState();
    _initAnimations();
    _navigateToLogin();
  }

  void _initAnimations() {
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 800),
    );
    _scaleAnimation = Tween<double>(begin: 0.9, end: 1.0).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOutQuart),
    );
    _fadeAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn));
    _slideAnimation = Tween<Offset>(
      begin: const Offset(0.0, 0.3),
      end: Offset.zero,
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutQuart));
    _controller.forward();
  }

  void _navigateToLogin() {
    Future.delayed(const Duration(seconds: 1), () {
      if (mounted) {
        Navigator.pushReplacement(
          context,
          PageRouteBuilder(
            pageBuilder: (_, __, ___) => const Login(),
            transitionsBuilder: (_, animation, __, child) =>
                FadeTransition(opacity: animation, child: child),
            transitionDuration: const Duration(milliseconds: 500),
          ),
        );
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF0A192F),
      body: Stack(
        children: [_buildBackgroundCircles(), Center(child: _buildContent())],
      ),
    );
  }

  Widget _buildBackgroundCircles() {
    return Stack(
      children: [
        Positioned(
          top: -50,
          right: -50,
          child: Container(
            width: 200,
            height: 200,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: Color(0xFF1E3A8A).withOpacity(0.2),
            ),
          ),
        ),
        Positioned(
          bottom: -100,
          left: -100,
          child: Container(
            width: 300,
            height: 300,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: Color(0xFF1E3A8A).withOpacity(0.1),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildContent() {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Directionality(
        textDirection: TextDirection.rtl,
        child: ScaleTransition(
          scale: _scaleAnimation,
          child: FadeTransition(
            opacity: _fadeAnimation,
            child: SlideTransition(
              position: _slideAnimation,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  _buildAppLogo(),
                  const SizedBox(height: 20),
                  _buildAppTitle(),
                  const SizedBox(height: 5),
                  _buildAppSubtitle(),
                  const SizedBox(height: 30),
                  _buildLoadingIndicator(),
                  const SizedBox(height: 15),
                  _buildLoadingText(),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildAppLogo() {
    return Hero(
      tag: 'app-logo',
      child: Container(
        padding: const EdgeInsets.all(15),
        decoration: BoxDecoration(
          color: Colors.white.withOpacity(0.1),
          shape: BoxShape.circle,
          border: Border.all(color: Colors.white.withOpacity(0.2), width: 1.5),
        ),
        child: Image.asset(
          'assets/img/control.png',
          height: 80,
          color: Colors.white.withOpacity(0.9),
        ),
      ),
    );
  }

  Widget _buildAppTitle() {
    return const Text(
      'Micro Panel',
      style: TextStyle(
        fontSize: 30,
        fontWeight: FontWeight.bold,
        color: Colors.white,
        letterSpacing: 1.2,
      ),
    );
  }

  Widget _buildAppSubtitle() {
    return const Text(
      'نظام إدارة أجهزة الميكروتك',
      style: TextStyle(color: Colors.white70, fontSize: 14),
    );
  }

  Widget _buildLoadingIndicator() {
    return SizedBox(
      width: 180,
      child: ClipRRect(
        borderRadius: BorderRadius.circular(8),
        child: LinearProgressIndicator(
          valueColor: AlwaysStoppedAnimation<Color>(
            Colors.white.withOpacity(0.9),
          ),
          backgroundColor: Colors.white.withOpacity(0.2),
          minHeight: 5,
        ),
      ),
    );
  }

  Widget _buildLoadingText() {
    return const Text(
      'جاري التحميل...',
      style: TextStyle(color: Colors.white, fontSize: 14),
    );
  }
}

class MikroTikApi {
  Socket? _socket;
  final String host;
  final int port;
  final String user, pass;
  final _recvBuffer = <int>[];

  MikroTikApi({
    required this.host,
    this.port = 8728,
    required this.user,
    required this.pass,
  });

  Future<void> connect() async {
    _socket = await Socket.connect(host, port);
    _socket!.listen(_onData, onError: _onError, onDone: _onDone);
  }

  void _onData(Uint8List chunk) {
    _recvBuffer.addAll(chunk);
  }

  void _onError(e) => throw 'Socket error: $e';
  void _onDone() => _socket = null;

  Uint8List _encodeWord(String s) {
    final b = utf8.encode(s);
    final len = b.length;
    final header = <int>[];
    if (len < 0x80)
      header.add(len);
    else if (len < 0x4000) {
      header.add((len >> 8) | 0x80);
      header.add(len & 0xFF);
    } else if (len < 0x200000) {
      header.add((len >> 16) | 0xC0);
      header.add((len >> 8) & 0xFF);
      header.add(len & 0xFF);
    } else {
      header.add((len >> 24) | 0xE0);
      header.add((len >> 16) & 0xFF);
      header.add((len >> 8) & 0xFF);
      header.add(len & 0xFF);
    }
    return Uint8List.fromList([...header, ...b]);
  }

  Future<void> sendSentence(List<String> words) async {
    final out = <int>[];
    for (var w in words) out.addAll(_encodeWord(w));
    out.add(0);
    _socket!.add(out);
    await _socket!.flush();
  }

  Future<List<List<String>>> _readSentences() async {
    final sentences = <List<String>>[];
    while (true) {
      await Future.delayed(Duration(milliseconds: 100));

      // تحقق من وجود بيانات في المخزن المؤقت
      if (_recvBuffer.isEmpty) continue;

      final buf = List<int>.from(_recvBuffer);
      try {
        var i = 0;
        while (i < buf.length) {
          final sentence = <String>[];
          while (i < buf.length && buf[i] != 0) {
            int len = buf[i++];
            int bytesCount = 1;

            if (len & 0x80 != 0) {
              bytesCount = (len & 0xC0) == 0x80
                  ? 2
                  : (len & 0xE0) == 0xC0
                      ? 3
                      : 4;
              len = ((len & 0x7F) << ((bytesCount - 1) * 8));

              for (int j = 0; j < bytesCount - 1 && i < buf.length; j++) {
                len |= buf[i++] << ((bytesCount - 2 - j) * 8);
              }
            }

            if (i + len > buf.length) {
              // البيانات غير مكتملة، نعيد المؤشر ونخرج
              i -= bytesCount;
              break;
            }

            sentence.add(utf8.decode(buf.sublist(i, i + len)));
            i += len;
          }

          if (i < buf.length && buf[i] == 0) {
            i++; // تخطي حرف الإنهاء
            sentences.add(sentence);

            // إذا كانت الجملة تحتوي على !done، نخرج
            if (sentence.isNotEmpty && sentence.first == '!done') {
              _recvBuffer.removeRange(0, i);
              return sentences;
            }
          } else {
            break; // بيانات غير مكتملة
          }
        }

        _recvBuffer.removeRange(0, i);

        // إذا وجدنا جملة !done نعود بالنتيجة
        if (sentences.any((s) => s.isNotEmpty && s.first == '!done')) {
          return sentences;
        }
      } catch (e) {
        print('Error parsing sentences: $e');
        break;
      }
    }
    return sentences;
  }

  Future<bool> login() async {
    await sendSentence(['/login', '=name=$user', '=password=$pass']);
    final resp = await _readSentences();
    return resp.any((s) => s.first == '!done');
  }

  Future<List<Map<String, String>>> fetchHotspotUsers() async {
    await sendSentence(['/ip/hotspot/user/print']);
    final resp = await _readSentences();
    return resp.where((s) => s.first == '!re').map((s) {
      final m = <String, String>{};
      for (var tok in s.skip(1)) {
        if (tok.startsWith('=')) {
          final idx = tok.indexOf('=', 1);
          if (idx != -1) {
            final key = tok.substring(1, idx);
            final value = tok.substring(idx + 1);
            m[key] = value;
          }
        }
      }

      return m;
    }).toList();
  }

  void close() => _socket?.destroy();
}

class Login extends StatefulWidget {
  const Login({super.key});

  @override
  State<Login> createState() => _LoginState();
}

class _LoginState extends State<Login> {
  final _formKey = GlobalKey<FormState>();
  final List<TextEditingController> _ipControllers = List.generate(
    4,
    (index) => TextEditingController(),
  );
  final List<FocusNode> _ipFocusNodes = List.generate(
    4,
    (index) => FocusNode(),
  );
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();
  final _portController = TextEditingController(text: '8728');
  bool _isLoading = false;
  bool _obscurePassword = true;
  bool _autoFetchEnabled = false;
  bool _hasSavedCredentials = false;
  Map<String, dynamic>? _savedCredentials;

  @override
  void initState() {
    super.initState();
    _loadSavedCredentials();
    for (int i = 0; i < _ipFocusNodes.length; i++) {
      _ipFocusNodes[i].onKey = (node, event) {
        if (event.logicalKey == LogicalKeyboardKey.tab) {
          if (event.isShiftPressed) return KeyEventResult.ignored;
          if (i > 0) {
            FocusScope.of(context).requestFocus(_ipFocusNodes[i - 1]);
          } else {
            FocusScope.of(context).requestFocus(_ipFocusNodes[0]);
          }
          return KeyEventResult.handled;
        }
        return KeyEventResult.ignored;
      };
    }
  }

  Future<void> _loadSavedCredentials() async {
    try {
      final directory = await getApplicationDocumentsDirectory();
      final file = File('${directory.path}/login_credentials.json');
      if (await file.exists()) {
        final contents = await file.readAsString();
        final credentials = jsonDecode(contents);
        if (credentials != null && credentials is Map) {
          setState(() {
            _savedCredentials = Map<String, dynamic>.from(credentials);
            _hasSavedCredentials = true;
            final savedIp = _savedCredentials?['ip']?.split('.') ?? [];
            for (int i = 0; i < 4 && i < savedIp.length; i++) {
              _ipControllers[i].text = savedIp[i];
            }
            _usernameController.text = _savedCredentials?['username'] ?? '';
            _passwordController.text = _savedCredentials?['password'] ?? '';
            _portController.text = _savedCredentials?['port'] ?? '8728';
          });
          print('done');
        }
      }
    } catch (e) {}
  }

  Future<void> _saveCredentials() async {
    try {
      final directory = await getApplicationDocumentsDirectory();
      final file = File('${directory.path}/login_credentials.json');
      final ip = _ipControllers.map((c) => c.text).join('.');
      final credentials = {
        'ip': ip,
        'username': _usernameController.text,
        'password': _passwordController.text,
        'port': _portController.text,
      };
      await file.writeAsString(jsonEncode(credentials));
      setState(() {
        _hasSavedCredentials = true;
        _savedCredentials = credentials;
      });
    } catch (e) {}
  }

  @override
  void dispose() {
    for (var controller in _ipControllers) controller.dispose();
    for (var node in _ipFocusNodes) node.dispose();
    _usernameController.dispose();
    _passwordController.dispose();
    _portController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final isMobile = size.width < 600;
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        backgroundColor: const Color(0xFF0A192F),
        body: SafeArea(
          child: LayoutBuilder(
            builder: (context, constraints) {
              if (constraints.maxWidth > 800) {
                return Row(
                  children: [
                    Expanded(
                      flex: 5,
                      child: Container(
                        padding: const EdgeInsets.symmetric(horizontal: 40),
                        color: const Color(0xFF0A192F),
                        child: Center(child: _buildLoginForm(isMobile)),
                      ),
                    ),
                    Expanded(
                      flex: 6,
                      child: Container(
                        decoration: const BoxDecoration(
                          gradient: LinearGradient(
                            begin: Alignment.topCenter,
                            end: Alignment.bottomCenter,
                            colors: [Color(0xFF1E3A8A), Color(0xFF0A192F)],
                          ),
                        ),
                        child: Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Icon(
                                Icons.router_outlined,
                                size: 150,
                                color: Colors.white,
                              ),
                              const SizedBox(height: 20),
                              const Text(
                                'مرحبًا بك في Micro Panel',
                                style: TextStyle(
                                  color: Colors.white,
                                  fontSize: 28,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              const SizedBox(height: 10),
                              const Text(
                                'نظام إدارة أجهزة الميكروتك\n'
                                'بكل سهولة واحترافية',
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                  color: Colors.white70,
                                  fontSize: 18,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                );
              } else {
                return CustomScrollView(
                  slivers: [
                    SliverFillRemaining(
                      hasScrollBody: false,
                      child: Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 20,
                          vertical: 40,
                        ),
                        child: _buildLoginForm(isMobile),
                      ),
                    ),
                  ],
                );
              }
            },
          ),
        ),
      ),
    );
  }

  Widget _buildLoginForm(bool isMobile) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          _buildAppHeader(isMobile),
          const SizedBox(height: 30),
          _buildIpFields(),
          const SizedBox(height: 12),
          _buildUsernameField(),
          const SizedBox(height: 12),
          _buildPasswordField(),
          const SizedBox(height: 12),
          _buildPortField(),
          const SizedBox(height: 15),
          _buildAutoFetchCheckbox(),
          const SizedBox(height: 25),
          _buildLoginButton(),
          const SizedBox(height: 15),
        ],
      ),
    );
  }

  Widget _buildAppHeader(bool isMobile) {
    return Column(
      children: [
        Hero(
          tag: 'app-icon',
          child: Icon(
            Icons.router_outlined,
            size: isMobile ? 80 : 100,
            color: Colors.white,
          ),
        ),
        const SizedBox(height: 10),
        const Text(
          'Micro Panel',
          style: TextStyle(
            fontSize: 24,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
        const SizedBox(height: 4),
        const Text(
          'نظام إدارة أجهزة الميكروتك',
          style: TextStyle(color: Colors.white70, fontSize: 13),
        ),
      ],
    );
  }

  Widget _buildIpFields() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.only(bottom: 8.0, right: 8.0),
          child: Text('عنوان IP', style: TextStyle(color: Colors.white70)),
        ),
        Row(
          textDirection: TextDirection.ltr,
          children: [
            for (int i = 0; i <= 3; i++) ...[
              Expanded(
                child: TextFormField(
                  controller: _ipControllers[i],
                  validator: (value) => _validateIpPart(value, i),
                  style: const TextStyle(color: Colors.white),
                  decoration: InputDecoration(
                    labelStyle: const TextStyle(color: Colors.white70),
                    filled: true,
                    fillColor: Colors.white.withOpacity(0.1),
                    contentPadding: const EdgeInsets.symmetric(
                      vertical: 14,
                      horizontal: 16,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide: BorderSide(
                        color: Colors.white.withOpacity(0.2),
                      ),
                    ),
                    focusedBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide: const BorderSide(color: Color(0xFF3B82F6)),
                    ),
                  ),
                  keyboardType: TextInputType.number,
                  textInputAction:
                      i < 3 ? TextInputAction.next : TextInputAction.done,
                  inputFormatters: [
                    FilteringTextInputFormatter.digitsOnly,
                    LengthLimitingTextInputFormatter(3),
                  ],
                  focusNode: _ipFocusNodes[i],
                  onChanged: (value) {
                    if (value.length == 3 && i < 3) {
                      FocusScope.of(context).requestFocus(_ipFocusNodes[i + 1]);
                    }
                  },
                  textAlign: TextAlign.center,
                ),
              ),
              if (i < 3)
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4.0),
                  child: Text('.', style: TextStyle(color: Colors.white)),
                ),
            ],
          ],
        ),
      ],
    );
  }

  Widget _buildUsernameField() {
    return TextFormField(
      controller: _usernameController,
      validator: (value) => _validateRequired(value, 'اسم المستخدم'),
      style: const TextStyle(color: Colors.white),
      decoration: InputDecoration(
        labelText: 'اسم المستخدم',
        labelStyle: const TextStyle(color: Colors.white70),
        prefixIcon: Icon(Icons.person_outline, color: Colors.white70),
        filled: true,
        fillColor: Colors.white.withOpacity(0.1),
        contentPadding: const EdgeInsets.symmetric(
          vertical: 14,
          horizontal: 16,
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(color: Colors.white.withOpacity(0.2)),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: const BorderSide(color: Color(0xFF3B82F6)),
        ),
      ),
      textInputAction: TextInputAction.next,
      onFieldSubmitted: (_) => FocusScope.of(
        context,
      ).requestFocus(_passwordController as FocusNode?),
    );
  }

  Widget _buildPasswordField() {
    return TextFormField(
      controller: _passwordController,
      obscureText: _obscurePassword,
      validator: (value) =>
          value == null || value.isEmpty ? 'يرجى إدخال كلمة المرور' : null,
      style: const TextStyle(color: Colors.white),
      decoration: InputDecoration(
        labelText: 'كلمة المرور',
        labelStyle: const TextStyle(color: Colors.white70),
        prefixIcon: Icon(Icons.lock_outline, color: Colors.white70),
        suffixIcon: IconButton(
          icon: Icon(
            _obscurePassword ? Icons.visibility_off : Icons.visibility,
            color: Colors.white70,
          ),
          onPressed: () => setState(() => _obscurePassword = !_obscurePassword),
        ),
        filled: true,
        fillColor: Colors.white.withOpacity(0.1),
        contentPadding: const EdgeInsets.symmetric(
          vertical: 14,
          horizontal: 16,
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(color: Colors.white.withOpacity(0.2)),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: const BorderSide(color: Color(0xFF3B82F6)),
        ),
      ),
      textInputAction: TextInputAction.next,
      onFieldSubmitted: (_) => _connectToMikrotik(),
    );
  }

  Widget _buildPortField() {
    return TextFormField(
      controller: _portController,
      validator: _validatePort,
      style: const TextStyle(color: Colors.white),
      decoration: InputDecoration(
        labelText: 'المنفذ',
        labelStyle: const TextStyle(color: Colors.white70),
        prefixIcon: Icon(Icons.settings_ethernet, color: Colors.white70),
        filled: true,
        fillColor: Colors.white.withOpacity(0.1),
        contentPadding: const EdgeInsets.symmetric(
          vertical: 14,
          horizontal: 16,
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(color: Colors.white.withOpacity(0.2)),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: const BorderSide(color: Color(0xFF3B82F6)),
        ),
      ),
      keyboardType: TextInputType.number,
      onFieldSubmitted: (_) => _connectToMikrotik(),
    );
  }

  Widget _buildAutoFetchCheckbox() {
    return Row(
      children: [
        Transform.scale(
          scale: 0.8,
          child: Checkbox(
            value: _autoFetchEnabled,
            onChanged: (value) =>
                setState(() => _autoFetchEnabled = value ?? false),
            fillColor: MaterialStateProperty.resolveWith<Color>((states) {
              if (states.contains(MaterialState.selected))
                return const Color(0xFF3B82F6);
              return Colors.transparent;
            }),
            side: BorderSide(color: Colors.white.withOpacity(0.5)),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(4),
            ),
          ),
        ),
        const SizedBox(width: 4),
        Text(
          'تحميل مستخدمي الهوتسبوت تلقائياً',
          style: TextStyle(color: Colors.white70, fontSize: 13),
        ),
      ],
    );
  }

  Widget _buildLoginButton() {
    return SizedBox(
      width: double.infinity,
      height: 48,
      child: ElevatedButton(
        onPressed: _isLoading ? null : _connectToMikrotik,
        style: ElevatedButton.styleFrom(
          backgroundColor: _isLoading ? Colors.grey : const Color(0xFF3B82F6),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
        ),
        child: _isLoading
            ? const SizedBox(
                width: 20,
                height: 20,
                child: CircularProgressIndicator(
                  color: Colors.white,
                  strokeWidth: 3,
                ),
              )
            : Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const [
                  Icon(Icons.login, color: Colors.white, size: 20),
                  SizedBox(width: 8),
                  Text(
                    'تسجيل الدخول',
                    style: TextStyle(fontSize: 15, color: Colors.white),
                  ),
                ],
              ),
      ),
    );
  }

  Future<void> _connectToMikrotik() async {
    if (!_formKey.currentState!.validate()) return;
    setState(() => _isLoading = true);
    try {
      final ip = _ipControllers.map((c) => c.text).join('.');
      final port = int.tryParse(_portController.text) ?? 8728;

      final client = RouterOSClient(
        address: ip,
        port: port,
        user: _usernameController.text,
        password: _passwordController.text,
        useSsl: false,
        verbose: false,
      );
      final isLoggedIn = await client.login();

      if (!isLoggedIn) {
        throw Exception("فشل تسجيل الدخول إلى جهاز الميكروتك");
      }

      await _saveCredentials();

      if (_autoFetchEnabled) {
        if (mounted) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => DataLoadingScreen(
                client: client,
                host: ip, // هذا هو عنوان IP من حقول الإدخال
                port: port, // هذا هو المنفذ من حقل الإدخال
                username: _usernameController.text,
                password: _passwordController.text,
              ),
            ),
          );
        }
      } else {
        if (mounted) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => RouterDetailsPage(client: client),
            ),
          );
        }
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('خطأ في الاتصال: ${e.toString()}')),
        );
      }
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  String? _validateRequired(String? value, String fieldName) {
    if (value == null || value.isEmpty) return 'يرجى إدخال $fieldName';
    final regex = RegExp(r'^[a-zA-Z0-9]+$');
    if (!regex.hasMatch(value))
      return 'يجب أن يحتوي $fieldName على أحرف إنجليزية وأرقام فقط';
    return null;
  }

  String? _validateIpPart(String? value, int part) {
    if (value == null || value.isEmpty) return 'يرجى إدخال جزء $part من الـ IP';
    if (!RegExp(r'^\d+$').hasMatch(value))
      return 'يجب أن يحتوي جزء $part على أرقام فقط';
    final num = int.tryParse(value) ?? 0;
    if (num < 0 || num > 255) return 'يجب أن يكون جزء $part بين 0 و 255';
    return null;
  }

  String? _validatePort(String? value) {
    if (value == null || value.isEmpty) return 'يرجى إدخال المنفذ';
    if (!RegExp(r'^\d+$').hasMatch(value))
      return 'يجب أن يحتوي المنفذ على أرقام فقط';
    final port = int.tryParse(value) ?? 0;
    if (port <= 0 || port > 65535) return 'يجب أن يكون المنفذ بين 1 و 65535';
    return null;
  }
}

class DataLoadingScreen extends StatefulWidget {
  final MikroTikApi? api; // يمكن إزالته لاحقًا إذا لم تعد تحتاج إليه
  final String host;
  final int port;
  final String username;
  final String password;
  final RouterOSClient client;

  const DataLoadingScreen({
    super.key,
    required this.client,
    required this.host,
    required this.port,
    required this.username,
    required this.password,
    this.api,
  });

  @override
  State<DataLoadingScreen> createState() => _DataLoadingScreenState();
}

class _DataLoadingScreenState extends State<DataLoadingScreen>
    with SingleTickerProviderStateMixin {
  bool _loading = true;
  int _userCount = 0;
  int _currentProgress = 0;
  bool _hasError = false;
  String _errorMessage = '';
  late final StreamController<int> _progressController;
  late final Stream<int> _progressStream;
  Isolate? _isolate;
  ReceivePort? _receivePort;
  int _totalUsers = 0;
  int _batchSize = 500;
  Timer? _simulationTimer;
  Random _random = Random();
  bool _realDataStarted = false;

  @override
  void initState() {
    super.initState();
    _progressController = StreamController<int>();
    _progressStream = _progressController.stream;
    _initDataLoading();
  }

  Future<void> _initDataLoading() async {
    try {
      await _startIsolate();
    } catch (e) {
      _handleError('فشل في بدء عملية الجلب: ${e.toString()}');
      print('$e');
    }
  }

  Future<void> _startIsolate() async {
    _receivePort = ReceivePort();

    await Isolate.spawn(
      _fetchUsersInBackground,
      _IsolateData(
        host: widget.host,
        port: widget.port,
        username: widget.username,
        password: widget.password,
        sendPort: _receivePort!.sendPort,
      ),
      onError: _receivePort!.sendPort,
      onExit: _receivePort!.sendPort,
    );
    _receivePort!.listen(_handleIsolateMessage);
  }

  void _handleIsolateMessage(dynamic message) {
    if (message is _ProgressUpdate) {
      if (!_realDataStarted) {
        _startSimulation(message.total);
        setState(() => _realDataStarted = true);
      }
      _updateProgress(message.current, message.total);
    } else if (message is List) {
      // نتأكد من أن القائمة تحتوي على بيانات
      if (message.isNotEmpty && message.first is Map<String, dynamic>) {
        _handleSuccess(message.cast<Map<String, dynamic>>());
      } else {
        _handleError('لم يتم استلام بيانات صحيحة من الـ Isolate');
      }
    } else if (message is String) {
      _handleError(message);
    } else {
      _handleError('استلام رسالة غير معروفة من الـ Isolate');
    }
  }

  void _startSimulation(int totalUsers) {
    _simulationTimer?.cancel();
    _totalUsers = totalUsers;
    _currentProgress = 0;
    _simulationTimer = Timer.periodic(Duration(milliseconds: 300), (timer) {
      if (_currentProgress < _totalUsers) {
        _currentProgress += 1 + _random.nextInt(40);
        if (_currentProgress > _totalUsers) {
          _currentProgress = _totalUsers;
        }
        _progressController.add(_currentProgress);
      } else {
        timer.cancel();
      }
    });
  }

  void _updateProgress(int current, int total) {
    if (!mounted) return;
    setState(() {
      _currentProgress = current;
      _totalUsers = total;
    });
    _progressController.add(current);
  }

  Future<void> _handleSuccess(List<Map<String, dynamic>> users) async {
    try {
      final directory = await getApplicationDocumentsDirectory();
      final file = File('${directory.path}/usermanager_users.json');
      await file.writeAsBytes(utf8.encode(jsonEncode(users)));
      if (mounted) {
        setState(() {
          _userCount = users.length;
          _loading = false;
        });
        Navigator.pushReplacement(
          context,
          MaterialPageRoute(
            builder: (context) => RouterDetailsPage(client: widget.client),
          ),
        );
      }
    } catch (e) {
      _handleError('فشل في حفظ البيانات: ${e.toString()}');
    }
  }

  void _handleError(String message) {
    if (!mounted) return;
    _simulationTimer?.cancel();
    setState(() {
      _hasError = true;
      _errorMessage = message;
      _loading = false;
    });
    _cleanUpResources();
  }

  void _cleanUpResources() {
    _simulationTimer?.cancel();
    _progressController.close();
    _isolate?.kill(priority: Isolate.immediate);
    _receivePort?.close();
  }

  static Future<void> _fetchUsersInBackground(_IsolateData isolateData) async {
    final sendPort = isolateData.sendPort;
    try {
      final api = MikroTikApi(
        host: isolateData.host,
        port: isolateData.port,
        user: isolateData.username,
        pass: isolateData.password,
      );

      await api.connect();
      bool loggedIn = await api.login();

      if (!loggedIn) {
        sendPort.send("فشل تسجيل الدخول إلى جهاز الميكروتك");
        return;
      }

      final users = await api.fetchHotspotUsers();
      sendPort.send(_ProgressUpdate(users.length, users.length));
      sendPort.send(users);
    } catch (e, stackTrace) {
      sendPort.send('حدث خطأ أثناء جلب البيانات:\n$e\n$stackTrace');
    }
  }

  @override
  void dispose() {
    _cleanUpResources();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF0A192F),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              if (_hasError)
                _buildErrorWidget()
              else if (_loading)
                _buildLoadingWidget()
              else
                _buildSuccessWidget(),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildErrorWidget() {
    return Column(
      children: [
        const Icon(Icons.error_outline, color: Colors.red, size: 40),
        const SizedBox(height: 16),
        Text(
          _errorMessage,
          style: const TextStyle(color: Colors.white, fontSize: 15),
          textAlign: TextAlign.center,
        ),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: () => Navigator.pop(context),
          style: ElevatedButton.styleFrom(
            backgroundColor: const Color(0xFF3B82F6),
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
          ),
          child: const Text('العودة', style: TextStyle(fontSize: 15)),
        ),
      ],
    );
  }

  Widget _buildLoadingWidget() {
    int displayedProgress = 0;
    int displayedTotal = _totalUsers;
    double displayedPercentage = 0.0;

    void updateDisplayedValues() {
      final progressDiff = _currentProgress - displayedProgress;
      final totalDiff = _totalUsers - displayedTotal;
      if (progressDiff > 0) {
        displayedProgress += (progressDiff / 5).ceil();
        if (displayedProgress > _currentProgress) {
          displayedProgress = _currentProgress;
        }
      }
      if (totalDiff > 0) {
        displayedTotal += (totalDiff / 3).ceil();
        if (displayedTotal > _totalUsers) {
          displayedTotal = _totalUsers;
        }
      }
      if (displayedTotal > 0) {
        displayedPercentage = (displayedProgress / displayedTotal * 100);
      }
    }

    return Column(
      children: [
        const SizedBox(
          width: 30,
          height: 30,
          child: CircularProgressIndicator(color: Colors.white, strokeWidth: 3),
        ),
        const SizedBox(height: 16),
        Text(
          _realDataStarted
              ? 'جاري جلب بيانات المستخدمين...'
              : 'جاري تهئية عملية الجلب...',
          style: const TextStyle(color: Colors.white, fontSize: 16),
        ),
        const SizedBox(height: 8),
        StreamBuilder<int>(
          stream: _progressStream,
          builder: (context, snapshot) {
            updateDisplayedValues();
            return Column(
              children: [
                Text(
                  '$displayedProgress من $displayedTotal (${displayedPercentage.toStringAsFixed(1)}%)',
                  style: const TextStyle(color: Colors.white70, fontSize: 13),
                ),
                const SizedBox(height: 16),
                LinearProgressIndicator(
                  value: displayedTotal > 0
                      ? displayedProgress / displayedTotal
                      : 0,
                  backgroundColor: Colors.white.withOpacity(0.2),
                  valueColor: const AlwaysStoppedAnimation<Color>(
                    Colors.blueAccent,
                  ),
                  minHeight: 6,
                ),
              ],
            );
          },
        ),
      ],
    );
  }

  Widget _buildSuccessWidget() {
    return Column(
      children: [
        const Icon(Icons.check_circle_outline, color: Colors.green, size: 40),
        const SizedBox(height: 16),
        Text(
          'تم جلب $_userCount مستخدم بنجاح',
          style: const TextStyle(color: Colors.white, fontSize: 16),
        ),
        const SizedBox(height: 8),
        const SizedBox(
          width: 20,
          height: 20,
          child: CircularProgressIndicator(
            color: Colors.white70,
            strokeWidth: 2,
          ),
        ),
        const SizedBox(height: 8),
        const Text(
          'جاري التوجيه إلى لوحة التحكم...',
          style: TextStyle(color: Colors.white70, fontSize: 13),
        ),
      ],
    );
  }
}

class HotspotUsersPage extends StatefulWidget {
  final MikroTikApi api;
  const HotspotUsersPage({super.key, required this.api});

  @override
  _HotspotUsersPageState createState() => _HotspotUsersPageState();
}

class _HotspotUsersPageState extends State<HotspotUsersPage> {
  List<Map<String, String>> allUsers = [];
  bool loading = false;
  String error = '';
  bool showUsers = false;
  bool dataLoaded = false;
  int currentPage = 0;
  final int usersPerPage = 25;

  List<Map<String, String>> get paginatedUsers {
    final start = currentPage * usersPerPage;
    final end = (start + usersPerPage > allUsers.length)
        ? allUsers.length
        : start + usersPerPage;
    return allUsers.sublist(start, end);
  }

  int get totalPages => (allUsers.length / usersPerPage).ceil();

  Future<void> fetchUsers() async {
    setState(() {
      loading = true;
      error = '';
      dataLoaded = false;
      showUsers = false;
    });
    try {
      final users = await widget.api.fetchHotspotUsers();
      setState(() {
        allUsers = users;
        loading = false;
        dataLoaded = true;
        currentPage = 0;
      });
    } catch (e) {
      setState(() {
        error = 'خطأ: $e';
        loading = false;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    fetchUsers();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('مستخدمي الهوتسبوت (${allUsers.length})'),
        backgroundColor: Colors.teal,
      ),
      body: Column(
        children: [
          SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton.icon(
                onPressed: loading ? null : fetchUsers,
                icon: Icon(Icons.download),
                label: Text('تحميل البيانات'),
              ),
              if (dataLoaded)
                ElevatedButton.icon(
                  onPressed: () => setState(() => showUsers = !showUsers),
                  icon: Icon(
                    showUsers ? Icons.visibility_off : Icons.visibility,
                  ),
                  label: Text(
                    showUsers ? 'إخفاء المستخدمين' : 'عرض المستخدمين',
                  ),
                ),
            ],
          ),
          SizedBox(height: 16),
          if (loading)
            Expanded(child: Center(child: CircularProgressIndicator())),
          if (error.isNotEmpty)
            Expanded(
              child: Center(
                child: Text(
                  error,
                  style: TextStyle(color: Colors.red, fontSize: 18),
                ),
              ),
            ),
          if (dataLoaded && !loading && error.isEmpty && showUsers)
            Expanded(
              child: Column(
                children: [
                  Expanded(
                    child: ListView.builder(
                      itemCount: paginatedUsers.length,
                      itemBuilder: (context, index) {
                        final user = paginatedUsers[index];
                        return Card(
                          margin: EdgeInsets.symmetric(
                            horizontal: 8,
                            vertical: 4,
                          ),
                          child: ListTile(
                            leading: Icon(Icons.person),
                            title: Text(
                              'الاسم: ${user['name'] ?? 'غير معروف'}',
                            ),
                            subtitle: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  'الباقة: ${user['profile'] ?? 'غير محدد'}',
                                ),
                                if (user['comment'] != null)
                                  Text('ملاحظات: ${user['comment']}'),
                              ],
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                  if (totalPages > 1)
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          IconButton(
                            icon: Icon(Icons.arrow_back),
                            onPressed: currentPage > 0
                                ? () => setState(() => currentPage--)
                                : null,
                          ),
                          Text('صفحة ${currentPage + 1} من $totalPages'),
                          IconButton(
                            icon: Icon(Icons.arrow_forward),
                            onPressed: currentPage < totalPages - 1
                                ? () => setState(() => currentPage++)
                                : null,
                          ),
                        ],
                      ),
                    ),
                ],
              ),
            ),
        ],
      ),
    );
  }
}

class _IsolateData {
  final String host;
  final int port;
  final String username;
  final String password;
  final SendPort sendPort;

  _IsolateData({
    required this.host,
    required this.port,
    required this.username,
    required this.password,
    required this.sendPort,
  });
}

class _ProgressUpdate {
  final int current;
  final int total;

  _ProgressUpdate(this.current, this.total);
}


اريد التعديل هذا في الجلب اليوزرمنجر بدل من الهتسبوت بنفس الطريقة عبر هذا الامر 
[admin@MikroTik] > user-manager/user/print