هناك مشاكل في اسنخراج الرصيد في هذا الكود مثلاَ كان الرصيد في الرسالة 12600 قان باستخراج 600 فقط
الكود
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:telephony/telephony.dart';
import 'package:flutter_contacts/flutter_contacts.dart';

const backgroundColor = Color(0xFFF9F9F9);
const primaryColor = Color(0xFF2C3E50);
const accentColor = Color(0xFFEBB429);
const progressColor = Color(0xFFB87333);

const tajawalFont = 'Tajawal';

class ThousandsSeparatorInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    String onlyDigits = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
    if (onlyDigits.isEmpty) return newValue.copyWith(text: '');
    final buffer = StringBuffer();
    int len = onlyDigits.length;
    for (int i = 0; i < len; i++) {
      buffer.write(onlyDigits[i]);
      int posFromRight = len - i - 1;
      if (posFromRight % 3 == 0 && i != len - 1) buffer.write(',');
    }
    return TextEditingValue(
      text: buffer.toString(),
      selection: TextSelection.collapsed(offset: buffer.length),
    );
  }
}

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

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

class _SplashScreenState extends State<SplashScreen>
    with TickerProviderStateMixin {
  bool _isLoading = true;
  bool _hasSavedBalance = false;

  int _currentBalance = 0;
  int _additionalBalance = 0;
  int _totalBalance = 0;

  late TextEditingController _balanceController;
  late TextEditingController _additionalBalanceController;

  bool _showAdditionalBalanceField = false;

  late AnimationController _animationController;
  late Animation<double> _logoScaleAnimation;
  late Animation<Offset> _contentSlideAnimation;
  late Animation<double> _fadeAnimation;

  final Telephony telephony = Telephony.instance;

  List<Contact> _contacts = [];

  @override
  void initState() {
    super.initState();
    _balanceController = TextEditingController();
    _additionalBalanceController = TextEditingController();

    _balanceController.addListener(_checkBalanceForAdditionalField);

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1000),
    );

    _balanceController.addListener(() {
      setState(() {});
    });
    _additionalBalanceController.addListener(() {
      setState(() {});
    });

    _logoScaleAnimation = Tween<double>(begin: 0.8, end: 1).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeOutBack),
    );
    _contentSlideAnimation = Tween<Offset>(
      begin: const Offset(0, 30),
      end: Offset.zero,
    ).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeOutQuart),
    );
    _fadeAnimation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );

    _animationController.forward();
    _loadBalance();
    _loadContacts();
  }

  Future<void> _loadContacts() async {
    bool permissionGranted = await FlutterContacts.requestPermission();
    if (!permissionGranted) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('يرجى السماح بالوصول إلى جهات الاتصال')),
        );
      }
      return;
    }
    final contacts = await FlutterContacts.getContacts(withProperties: true);
    if (mounted) {
      setState(() {
        _contacts = contacts;
      });
    }
  }

  Future<String?> _askUserForPhoneNumber() async {
    String? phoneNumber;
    await showDialog(
      context: context,
      builder: (context) {
        final controller = TextEditingController();
        String localSearchQuery = '';

        return StatefulBuilder(
          builder: (context, setStateDialog) {
            List<Contact> filteredContacts =
                _contacts.where((contact) {
                  final name = contact.displayName.toLowerCase();
                  final query = localSearchQuery.toLowerCase();

                  final matchesName = name.contains(query);
                  final matchesNumber = contact.phones.any(
                    (phone) => phone.number.toLowerCase().contains(query),
                  );

                  return matchesName || matchesNumber;
                }).toList();

            return AlertDialog(
              title: const Text('أدخل رقم جهة الاتصال أو اختر من القائمة'),
              content: SizedBox(
                width: double.maxFinite,
                height: 350,
                child: Column(
                  children: [
                    TextField(
                      controller: controller,
                      keyboardType: TextInputType.text,
                      decoration: const InputDecoration(
                        hintText: 'قم بكتابة اسم الشخص او رقم هاتفة',
                        suffixIcon: Icon(Icons.search),
                      ),
                      onChanged: (val) {
                        setStateDialog(() {
                          localSearchQuery = val;
                        });
                      },
                    ),
                    const SizedBox(height: 10),
                    Expanded(
                      child:
                          filteredContacts.isEmpty
                              ? const Center(child: Text('لا توجد جهات اتصال'))
                              : ListView.builder(
                                shrinkWrap: true,
                                itemCount: filteredContacts.length,
                                itemBuilder: (_, index) {
                                  final contact = filteredContacts[index];
                                  final phones = contact.phones;
                                  return ListTile(
                                    title: Text(contact.displayName),
                                    subtitle:
                                        phones.isNotEmpty
                                            ? Text(phones.first.number)
                                            : null,
                                    onTap: () {
                                      if (phones.isNotEmpty) {
                                        controller.text = phones.first.number;
                                      }
                                    },
                                  );
                                },
                              ),
                    ),
                  ],
                ),
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.of(context).pop(),
                  child: const Text('إلغاء'),
                ),
                TextButton(
                  onPressed: () {
                    phoneNumber = controller.text.trim();
                    Navigator.of(context).pop();
                  },
                  child: const Text('موافق'),
                ),
              ],
            );
          },
        );
      },
    );
    return phoneNumber;
  }

  Future<bool> _requestPermissions() async {
    PermissionStatus smsStatus = await Permission.sms.status;
    if (!smsStatus.isGranted) {
      smsStatus = await Permission.sms.request();
    }
    return smsStatus.isGranted;
  }

  Future<String?> _getLatestSmsFromNumber(String senderNumber) async {
    bool? permissionsGranted = await telephony.requestSmsPermissions;
    if (permissionsGranted != true) return null;

    String formatNumber(String number) {
      return number.replaceAll(RegExp(r'[^0-9]'), ''); // أبقي الأرقام فقط
    }

    String formattedSenderNumber = formatNumber(senderNumber);

    final List<SmsMessage> messages = await telephony.getInboxSms(
      columns: [SmsColumn.ADDRESS, SmsColumn.BODY],
      filter: SmsFilter.where(
        SmsColumn.ADDRESS,
      ).like('%$formattedSenderNumber%'),
      sortOrder: [OrderBy(SmsColumn.DATE_SENT, sort: Sort.DESC)],
    );

    if (messages.isNotEmpty) {
      return messages.first.body;
    }
    return null;
  }

  int extractBalanceFromMessage(String message) {
    RegExp regex = RegExp(
      r'(\d{1,9})\s*(ريال|ري|YR|SAR|﷼)',
      caseSensitive: false,
    );
    final match = regex.firstMatch(message);
    if (match != null) {
      String valueStr = match.group(1)!;
      return int.tryParse(valueStr) ?? 0;
    }
    return 0;
  }

  Future<void> _fetchBalanceFromSms() async {
    bool havePermissions = await _requestPermissions();
    if (!havePermissions) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('يرجى السماح بصلاحيات قراءة الرسائل')),
      );
      return;
    }

    final senderNumber = await _askUserForPhoneNumber();
    if (senderNumber == null || senderNumber.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('لم يتم إدخال رقم جهة اتصال')),
      );
      return;
    }

    String? smsText = await _getLatestSmsFromNumber(senderNumber);
    if (smsText == null) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('لم يتم العثور على رسائل من جهة الاتصال')),
      );
      return;
    }

    int balance = extractBalanceFromMessage(smsText);
    if (balance > 0) {
      final formattedBalance = _formatWithThousandsSeparator(balance);
      setState(() {
        _balanceController.text = formattedBalance;
      });

      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('تم جلب الرصيد من رسالة جهة الاتصال')),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('لم يتم العثور على رصيد صالح في الرسالة')),
      );
    }
  }

  Future<void> _loadBalance() async {
    final prefs = await SharedPreferences.getInstance();
    final savedData = prefs.getString('balance_data');

    if (savedData != null) {
      final Map<String, dynamic> jsonData = jsonDecode(savedData);

      setState(() {
        _currentBalance = jsonData['current_balance'] ?? 0;
        _additionalBalance = jsonData['additional_balance'] ?? 0;
        _totalBalance = jsonData['total_balance'] ?? 0;
        _hasSavedBalance = true;

        _balanceController.text = _formatWithThousandsSeparator(
          _currentBalance,
        );
        _showAdditionalBalanceField = true;

        _additionalBalanceController.text = '';
      });
    } else {
      setState(() {
        _showAdditionalBalanceField = false;
      });
    }

    setState(() {
      _isLoading = false;
    });
  }

  void _checkBalanceForAdditionalField() {
    final text = _balanceController.text.replaceAll(',', '').trim();
    final balance = int.tryParse(text) ?? 0;
    final additionalText =
        _additionalBalanceController.text.replaceAll(',', '').trim();
    final shouldShow = balance > 0 || additionalText.isNotEmpty;

    if (shouldShow != _showAdditionalBalanceField) {
      setState(() {
        _showAdditionalBalanceField = shouldShow;
        if (!_showAdditionalBalanceField) {
          _additionalBalanceController.clear();
        }
      });
    }
  }

  String _formatWithThousandsSeparator(int value) {
    final s = value.toString();
    final buffer = StringBuffer();
    final len = s.length;
    for (int i = 0; i < len; i++) {
      buffer.write(s[i]);
      final posFromRight = len - i - 1;
      if (posFromRight % 3 == 0 && i != len - 1) buffer.write(',');
    }
    return buffer.toString();
  }

  Future<void> _saveBalances({
    required int currentBalance,
    required int additionalBalance,
    required int totalBalance,
  }) async {
    final prefs = await SharedPreferences.getInstance();

    Map<String, dynamic> balanceData = {
      'current_balance': currentBalance,
      'additional_balance': additionalBalance,
      'total_balance': totalBalance,
    };

    await prefs.setString('balance_data', jsonEncode(balanceData));
  }

  void _onContinue() async {
    final currentInput = _balanceController.text.replaceAll(',', '').trim();
    final additionalInput =
        _additionalBalanceController.text.replaceAll(',', '').trim();

    final currentBalanceInput = int.tryParse(currentInput);
    final additionalBalanceInput = int.tryParse(
      additionalInput.isEmpty ? '0' : additionalInput,
    );

    if (currentBalanceInput == null || currentBalanceInput < 0) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text(
            'يرجى إدخال مبلغ رصيد صالح (صفر أو أكثر) في الرصيد الحالي',
            style: TextStyle(fontFamily: tajawalFont),
          ),
          behavior: SnackBarBehavior.floating,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          backgroundColor: Colors.red,
        ),
      );
      return;
    }

    if (additionalInput.isNotEmpty &&
        (additionalBalanceInput == null || additionalBalanceInput < 0)) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text(
            'يرجى إدخال مبلغ رصيد إضافي صالح (صفر أو أكثر) أو تركه فارغًا',
            style: TextStyle(fontFamily: tajawalFont),
          ),
          behavior: SnackBarBehavior.floating,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          backgroundColor: Colors.red,
        ),
      );
      return;
    }

    int totalBalance = currentBalanceInput + (additionalBalanceInput ?? 0);

    setState(() {
      _currentBalance = totalBalance;
      if (additionalBalanceInput != null && additionalBalanceInput > 0) {
        _additionalBalance = additionalBalanceInput;
      }
      _totalBalance = totalBalance;

      _balanceController.clear();
      _additionalBalanceController.clear();

      _showAdditionalBalanceField = false;

      _hasSavedBalance = true;
    });

    await _saveBalances(
      currentBalance: _currentBalance,
      additionalBalance: _additionalBalance,
      totalBalance: _totalBalance,
    );

    Navigator.pushReplacementNamed(context, '/home');
  }

  Widget _smallBalanceInfo(String label, int value) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(
          label,
          style: TextStyle(
            fontFamily: tajawalFont,
            color: Colors.grey[600],
            fontSize: 12,
          ),
        ),
        const SizedBox(height: 2),
        Text(
          _formatWithThousandsSeparator(value),
          style: TextStyle(
            fontFamily: tajawalFont,
            fontWeight: FontWeight.bold,
            color: primaryColor,
            fontSize: 14,
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backgroundColor,
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
          child:
              _isLoading
                  ? Center(
                    child: CircularProgressIndicator(
                      color: progressColor,
                      strokeWidth: 2,
                    ),
                  )
                  : Column(
                    children: [
                      Expanded(
                        child: SingleChildScrollView(
                          physics: const BouncingScrollPhysics(),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              const SizedBox(height: 40),
                              ScaleTransition(
                                scale: _logoScaleAnimation,
                                child: Container(
                                  width: 120,
                                  height: 120,
                                  decoration: BoxDecoration(
                                    color: const Color(
                                      0xFF69541D,
                                    ).withOpacity(0.05),
                                    shape: BoxShape.circle,
                                  ),
                                  child: Icon(
                                    Icons.currency_exchange_rounded,
                                    size: 60,
                                    color: const Color(
                                      0xFFEBB429,
                                    ).withOpacity(1),
                                  ),
                                ),
                              ),
                              const SizedBox(height: 40),
                              SlideTransition(
                                position: _contentSlideAnimation,
                                child: FadeTransition(
                                  opacity: _fadeAnimation,
                                  child: Column(
                                    children: [
                                      Text(
                                        ' مرحبًا بك في تطبيق حوّلها فايـبـرافـون',
                                        style: TextStyle(
                                          fontSize: 18,
                                          color: primaryColor,
                                          fontWeight: FontWeight.bold,
                                          height: 1.4,
                                          fontFamily: tajawalFont,
                                        ),
                                        textAlign: TextAlign.center,
                                      ),
                                      const SizedBox(height: 16),
                                      Text(
                                        'أدخل رصيدك الحالي أو أضف رصيدًا إضافيًا لبدء إدارة وتحويل رصيدك بسهولة',
                                        style: TextStyle(
                                          color: Colors.grey[700],
                                          height: 1.6,
                                          fontFamily: tajawalFont,
                                          fontSize: 14,
                                        ),
                                        textAlign: TextAlign.center,
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                              const SizedBox(height: 40),
                              SlideTransition(
                                position: _contentSlideAnimation,
                                child: FadeTransition(
                                  opacity: _fadeAnimation,
                                  child: TextField(
                                    controller: _balanceController,
                                    keyboardType: TextInputType.number,
                                    inputFormatters: [
                                      ThousandsSeparatorInputFormatter(),
                                    ],
                                    textAlign: TextAlign.right,
                                    style: TextStyle(
                                      fontWeight: FontWeight.w600,
                                      fontFamily: tajawalFont,
                                      color: primaryColor,
                                    ),
                                    decoration: InputDecoration(
                                      filled: true,
                                      fillColor: Colors.white,
                                      hintText: 'مثال: 1,000',
                                      hintStyle: TextStyle(
                                        fontSize: 13,
                                        fontFamily: tajawalFont,
                                        color: Colors.grey[500],
                                      ),
                                      labelText: 'الرصيد الحالي',
                                      labelStyle: TextStyle(
                                        fontFamily: tajawalFont,
                                        color: primaryColor,
                                      ),
                                      prefixIcon: Icon(
                                        Icons.account_balance_wallet,
                                        color: accentColor,
                                      ),
                                      suffixIcon:
                                          _balanceController.text.trim().isEmpty
                                              ? GestureDetector(
                                                onTap: _fetchBalanceFromSms,
                                                child: Padding(
                                                  padding: const EdgeInsets.all(
                                                    12.0,
                                                  ),
                                                  child: Icon(
                                                    Icons.sms,
                                                    color: accentColor,
                                                  ),
                                                ),
                                              )
                                              : null,
                                      border: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(12),
                                        borderSide: BorderSide(
                                          color: Colors.grey[300]!,
                                        ),
                                      ),
                                      enabledBorder: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(12),
                                        borderSide: BorderSide(
                                          color: Colors.grey[300]!,
                                        ),
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(12),
                                        borderSide: BorderSide(
                                          color: primaryColor,
                                          width: 2,
                                        ),
                                      ),
                                      floatingLabelBehavior:
                                          FloatingLabelBehavior.always,
                                      contentPadding:
                                          const EdgeInsets.symmetric(
                                            horizontal: 20,
                                            vertical: 16,
                                          ),
                                    ),
                                  ),
                                ),
                              ),
                              const SizedBox(height: 24),
                              if (_showAdditionalBalanceField)
                                SlideTransition(
                                  position: _contentSlideAnimation,
                                  child: FadeTransition(
                                    opacity: _fadeAnimation,
                                    child: TextField(
                                      controller: _additionalBalanceController,
                                      keyboardType: TextInputType.number,
                                      inputFormatters: [
                                        ThousandsSeparatorInputFormatter(),
                                      ],
                                      textAlign: TextAlign.right,
                                      style: TextStyle(
                                        fontWeight: FontWeight.w600,
                                        fontFamily: tajawalFont,
                                        color: primaryColor,
                                      ),
                                      decoration: InputDecoration(
                                        filled: true,
                                        fillColor: Colors.white,
                                        hintText: 'مثال: 500 (اختياري)',
                                        hintStyle: TextStyle(
                                          fontSize: 13,
                                          fontFamily: tajawalFont,
                                          color: Colors.grey[500],
                                        ),
                                        labelText: 'رصيد إضافي (اختياري)',
                                        labelStyle: TextStyle(
                                          fontFamily: tajawalFont,
                                          color: primaryColor,
                                        ),
                                        prefixIcon: Icon(
                                          Icons.add_circle_outline,
                                          color: accentColor,
                                        ),
                                        suffixIcon:
                                            (_additionalBalanceController.text
                                                    .trim()
                                                    .isEmpty)
                                                ? Icon(
                                                  Icons.warning_amber_outlined,
                                                  color: Colors.orange,
                                                )
                                                : null,
                                        border: OutlineInputBorder(
                                          borderRadius: BorderRadius.circular(
                                            12,
                                          ),
                                          borderSide: BorderSide(
                                            color: Colors.grey[300]!,
                                          ),
                                        ),
                                        enabledBorder: OutlineInputBorder(
                                          borderRadius: BorderRadius.circular(
                                            12,
                                          ),
                                          borderSide: BorderSide(
                                            color: Colors.grey[300]!,
                                          ),
                                        ),
                                        focusedBorder: OutlineInputBorder(
                                          borderRadius: BorderRadius.circular(
                                            12,
                                          ),
                                          borderSide: BorderSide(
                                            color: primaryColor,
                                            width: 2,
                                          ),
                                        ),
                                        floatingLabelBehavior:
                                            FloatingLabelBehavior.always,
                                        contentPadding:
                                            const EdgeInsets.symmetric(
                                              horizontal: 20,
                                              vertical: 16,
                                            ),
                                      ),
                                    ),
                                  ),
                                ),
                              if (_hasSavedBalance)
                                Padding(
                                  padding: const EdgeInsets.only(top: 24),
                                  child: Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceEvenly,
                                    children: [
                                      _smallBalanceInfo(
                                        'الرصيد السابق',
                                        _totalBalance - _additionalBalance,
                                      ),
                                      if (_showAdditionalBalanceField)
                                        _smallBalanceInfo(
                                          'الرصيد الإضافي',
                                          _additionalBalance,
                                        ),
                                      _smallBalanceInfo(
                                        'الإجمالي',
                                        _totalBalance,
                                      ),
                                    ],
                                  ),
                                ),
                            ],
                          ),
                        ),
                      ),
                      const SizedBox(height: 24),
                      SlideTransition(
                        position: _contentSlideAnimation,
                        child: FadeTransition(
                          opacity: _fadeAnimation,
                          child: SizedBox(
                            width: double.infinity,
                            child: ElevatedButton(
                              onPressed: _onContinue,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: accentColor,
                                foregroundColor: Colors.white,
                                padding: const EdgeInsets.symmetric(
                                  vertical: 16,
                                ),
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(12),
                                ),
                                elevation: 0,
                                shadowColor: Colors.transparent,
                              ),
                              child: Text(
                                'ابدأ الآن',
                                style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                  color: Colors.white,
                                  fontFamily: tajawalFont,
                                  fontSize: 16,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
        ),
      ),
    );
  }
}