اريد جعل الاتصال متسلسل لكن دون تدخل مني بعد النقر على زر اجراء مكالمة
الكود 
import 'package:flutter/material.dart';
import 'package:telephony/telephony.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:async';

void main() => runApp(SMSApp());

void onBackgroundMessage(SmsMessage message) {
  debugPrint("رسالة واردة في الخلفية: ${message.body}");
}

class SMSApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'تطبيق الرسائل والمكالمات',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF1A73E8),
          primary: const Color(0xFF1A73E8),
          secondary: const Color(0xFF4285F4),
          tertiary: const Color(0xFF34A853),
          background: const Color(0xFFF8F9FA),
          surface: Colors.white,
          onPrimary: Colors.white,
          onSecondary: Colors.white,
          onBackground: const Color(0xFF202124),
          onSurface: const Color(0xFF202124),
        ),
        useMaterial3: true,
        fontFamily: 'Tajawal',
        appBarTheme: AppBarTheme(
          backgroundColor: const Color(0xFF1A73E8),
          foregroundColor: Colors.white,
          elevation: 0,
          centerTitle: true,
          titleTextStyle: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
          iconTheme: const IconThemeData(color: Colors.white),
        ),
        cardTheme: CardTheme(
          color: Colors.white,
          elevation: 1,
          margin: const EdgeInsets.all(8),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          surfaceTintColor: Colors.white,
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: const Color(0xFF1A73E8),
            foregroundColor: Colors.white,
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            elevation: 0,
            textStyle: const TextStyle(
              fontWeight: FontWeight.w600,
              fontSize: 16,
            ),
          ),
        ),
        outlinedButtonTheme: OutlinedButtonThemeData(
          style: OutlinedButton.styleFrom(
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            side: const BorderSide(width: 1.5, color: Color(0xFF1A73E8)),
            textStyle: const TextStyle(fontWeight: FontWeight.w600),
          ),
        ),
        textButtonTheme: TextButtonThemeData(
          style: TextButton.styleFrom(
            foregroundColor: const Color(0xFF1A73E8),
            textStyle: const TextStyle(fontWeight: FontWeight.w600),
          ),
        ),
        snackBarTheme: SnackBarThemeData(
          behavior: SnackBarBehavior.floating,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
          backgroundColor: const Color(0xFF1A73E8),
          contentTextStyle: const TextStyle(color: Colors.white),
        ),
        inputDecorationTheme: InputDecorationTheme(
          filled: true,
          fillColor: Colors.grey.shade50,
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: BorderSide.none,
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: Color(0xFF1A73E8), width: 2),
          ),
          contentPadding: const EdgeInsets.symmetric(
            horizontal: 16,
            vertical: 14,
          ),
        ),
        dialogTheme: DialogTheme(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          backgroundColor: Colors.white,
          elevation: 8,
          surfaceTintColor: Colors.white,
        ),
        listTileTheme: ListTileThemeData(
          iconColor: const Color(0xFF1A73E8),
          contentPadding: const EdgeInsets.symmetric(horizontal: 16),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
        ),
        dividerTheme: DividerThemeData(
          color: Colors.grey.shade200,
          thickness: 1,
          space: 0,
        ),
        progressIndicatorTheme: const ProgressIndicatorThemeData(
          color: Color(0xFF1A73E8),
        ),
        chipTheme: ChipThemeData(
          backgroundColor: Colors.grey.shade100,
          selectedColor: const Color(0xFF1A73E8),
          secondarySelectedColor: const Color(0xFF1A73E8),
          disabledColor: Colors.grey.shade300,
          labelStyle: const TextStyle(color: Colors.black),
          secondaryLabelStyle: const TextStyle(color: Colors.white),
          brightness: Brightness.light,
          padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
        ),
      ),
      home: SMSHomePage(),
    );
  }
}

class SMSHomePage extends StatefulWidget {
  @override
  _SMSHomePageState createState() => _SMSHomePageState();
}

class _SMSHomePageState extends State<SMSHomePage> with WidgetsBindingObserver {
  final Telephony _telephony = Telephony.instance;
  List<SmsMessage> _messages = [];
  bool _isLoading = true;

  // الرقم المستخدم لتصفية الرسائل غير المقروءة
  String? _savedContact;

  // أرقام المكالمات المستقلة (يمكن أن تكون أرقام مختلفة)
  List<String> _callPhoneNumbers = [];

  SharedPreferences? _prefs;
  bool _isListening = false;

  String? _savedTextPattern;
  double _similarityThreshold = 0.8;
  bool _usePartialMatch = true;

  bool _isCalling = false;
  bool _permissionRequested = false;

  final List<Map<String, dynamic>> _callLogs = [];

  int _currentCallIndex = 0;
  StreamController<int> _callProgressController =
      StreamController<int>.broadcast();

  // ======== HELPER FUNCTIONS ==========

  Future<String?> getContactNameFromNumber(String? number) async {
    if (number == null || number.isEmpty) return null;

    String normalizedNumber = number.replaceAll(RegExp(r'[^\d+]'), '');

    final status = await Permission.contacts.status;
    if (!status.isGranted) {
      final result = await Permission.contacts.request();
      if (!result.isGranted) return null;
    }

    final allContacts = await FlutterContacts.getContacts(
      withProperties: true,
      withThumbnail: false,
    );

    return allContacts
        .where(
          (contact) => contact.phones.any((phone) {
            String contactNumber = phone.number.replaceAll(
              RegExp(r'[^\d+]'),
              '',
            );
            return contactNumber.contains(normalizedNumber) ||
                normalizedNumber.contains(contactNumber);
          }),
        )
        .map((contact) => contact.displayName)
        .firstOrNull;
  }

  Future<bool> _contactNameMatches(String? number, String name) async {
    String? contactName = await getContactNameFromNumber(number);
    if (contactName == null) return false;
    return _isTextSimilar(contactName, name);
  }

  bool _isTextSimilar(String text1, String text2) {
    if (text1.isEmpty || text2.isEmpty) return false;

    if (_usePartialMatch) {
      return partialRatio(text1.toLowerCase(), text2.toLowerCase()) >=
          (_similarityThreshold * 100);
    } else {
      return text1.toLowerCase().contains(text2.toLowerCase());
    }
  }

  Future<bool> _isMessageFromSavedContact(SmsMessage message) async {
    if (_savedContact == null || _savedContact!.isEmpty) return false;

    if (RegExp(r'^[\d+\s\-()]+$').hasMatch(_savedContact!)) {
      String normalizedSaved = _savedContact!.replaceAll(RegExp(r'[^\d+]'), '');
      String normalizedMsg =
          message.address?.replaceAll(RegExp(r'[^\d+]'), '') ?? '';
      return normalizedMsg.contains(normalizedSaved);
    } else {
      return await _contactNameMatches(message.address, _savedContact!);
    }
  }

  bool _isUnreadMessage(SmsMessage message) {
    if (message.read is bool) {
      return !(message.read as bool);
    } else if (message.read is String) {
      return message.read == "0";
    } else {
      return true;
    }
  }

  // ======== INITIALIZATION ==========
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _initApp();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _stopSmsListener();
    _callProgressController.close();
    super.dispose();
  }

  Future<void> _initApp() async {
    _prefs = await SharedPreferences.getInstance();
    setState(() {
      _savedContact = _prefs?.getString('savedContact');
      _savedTextPattern = _prefs?.getString('savedTextPattern');
      _usePartialMatch = _prefs?.getBool('usePartialMatch') ?? true;
      _similarityThreshold = _prefs?.getDouble('similarityThreshold') ?? 0.8;
      final savedCallNumbers = _prefs?.getStringList('callPhoneNumbers');
      if (savedCallNumbers != null) _callPhoneNumbers = savedCallNumbers;
    });

    await _requestPermissions();
    await _loadMessagesAutomatically();
    _startSmsListener();
  }

  Future<bool> _requestPermissions() async {
    if (_permissionRequested) return true;
    _permissionRequested = true;

    final smsStatus = await Permission.sms.status;
    final phoneStatus = await Permission.phone.status;
    final contactsStatus = await Permission.contacts.status;

    if (!smsStatus.isGranted ||
        !phoneStatus.isGranted ||
        !contactsStatus.isGranted) {
      final permissions =
          await [
            Permission.sms,
            Permission.phone,
            Permission.contacts,
          ].request();

      if (!permissions[Permission.sms]!.isGranted) {
        _showSnackBar("يجب منح إذن الرسائل لاستخدام التطبيق");
        return false;
      }

      if (!permissions[Permission.phone]!.isGranted) {
        _showSnackBar("يجب منح إذن المكالمات لاستخدام التطبيق");
        return false;
      }

      if (!permissions[Permission.contacts]!.isGranted) {
        _showSnackBar("يجب منح إذن جهات الاتصال لاستخدام التطبيق");
        return false;
      }
    }

    return true;
  }

  // ======== الرسائل ==========
  Future<void> _loadMessagesAutomatically() async {
    if (_savedContact == null || _savedContact!.isEmpty) {
      setState(() => _isLoading = false);
      return;
    }

    setState(() => _isLoading = true);

    try {
      final List<SmsMessage> allMessages = await _telephony.getInboxSms(
        columns: [
          SmsColumn.ADDRESS,
          SmsColumn.BODY,
          SmsColumn.DATE,
          SmsColumn.READ,
        ],
      );

      // جلب الرسائل غير المقروءة فقط
      final List<SmsMessage> unreadMessages =
          allMessages.where(_isUnreadMessage).toList();

      // تصفية حسب جهة الاتصال المختارة
      final List<SmsMessage> filteredByContact = [];
      for (final msg in unreadMessages) {
        if (await _isMessageFromSavedContact(msg)) {
          filteredByContact.add(msg);
        }
      }

      // تطبيق فلتر النص إن وجد
      List<SmsMessage> finalMessages;
      if (_savedTextPattern != null && _savedTextPattern!.isNotEmpty) {
        finalMessages =
            filteredByContact.where((msg) {
              final bodyText = msg.body ?? '';
              return _isTextSimilar(bodyText, _savedTextPattern!);
            }).toList();
      } else {
        finalMessages = filteredByContact;
      }

      if (mounted) {
        setState(() {
          _messages = finalMessages;
          _isLoading = false;
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() => _isLoading = false);
        _showSnackBar("خطأ في تحميل الرسائل: ${e.toString()}");
      }
    }
  }

  void _startSmsListener() {
    if (_isListening || _savedContact == null) return;

    _telephony.listenIncomingSms(
      onNewMessage: (SmsMessage message) async {
        if (await _isMessageFromSavedContact(message) &&
            _isUnreadMessage(message) &&
            (_savedTextPattern == null ||
                _savedTextPattern!.isEmpty ||
                _isTextSimilar(message.body ?? '', _savedTextPattern!))) {
          _addNewMessage(message);
        }
      },
      onBackgroundMessage: onBackgroundMessage,
      listenInBackground: true,
    );
    _isListening = true;
  }

  void _stopSmsListener() {
    _telephony.listenIncomingSms(onNewMessage: (SmsMessage message) {});
    _isListening = false;
  }

  void _addNewMessage(SmsMessage message) {
    if (mounted) {
      setState(() {
        _messages.insert(0, message);
      });
      _showSnackBar("تم استقبال رسالة جديدة من ${message.address}");
    }
  }

  // تعديل وحفظ رقم المتابعة للرسائل (رقم منفصل)
  Future<void> _saveMessageContact(String contact) async {
    await _prefs?.setString('savedContact', contact);
    if (mounted) {
      setState(() {
        _savedContact = contact;
        _messages.clear();
      });
    }
    await _loadMessagesAutomatically();
  }

  // =================== إدارة المكالمات ==================

  // حفظ قائمة أرقام المكالمات
  Future<void> _saveCallPhoneNumbers(List<String> numbers) async {
    await _prefs?.setStringList('callPhoneNumbers', numbers);
    setState(() {
      _callPhoneNumbers = numbers;
    });
  }

  // فتح حوار لاختيار أرقام المكالمات من جهات الاتصال (يمكن اختيار عدة أرقام)
  void _showPhoneNumbersSelectionDialog() async {
    final granted = await Permission.contacts.request();
    if (!granted.isGranted) {
      _showSnackBar("يجب منح إذن الوصول لجهات الاتصال لاختيار الأرقام");
      return;
    }

    final contacts = await FlutterContacts.getContacts(
      withProperties: true,
      withThumbnail: false,
    );

    List<String> selectedNumbers = List.from(_callPhoneNumbers);

    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder:
          (context) => StatefulBuilder(
            builder: (context, setModalState) {
              return Padding(
                padding: EdgeInsets.only(
                  bottom: MediaQuery.of(context).viewInsets.bottom + 10,
                  left: 16,
                  right: 16,
                  top: 24,
                ),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Row(
                      children: [
                        IconButton(
                          icon: const Icon(Icons.close),
                          onPressed: () => Navigator.pop(context),
                        ),
                        Expanded(
                          child: Text(
                            "اختر أرقام المكالمات من جهات الاتصال",
                            style: Theme.of(context).textTheme.titleLarge
                                ?.copyWith(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.center,
                          ),
                        ),
                        const SizedBox(width: 48),
                      ],
                    ),
                    const SizedBox(height: 16),
                    Expanded(
                      child: ListView.builder(
                        itemCount: contacts.length,
                        itemBuilder: (context, index) {
                          final contact = contacts[index];
                          final phoneList =
                              contact.phones.map((p) => p.number).toList();

                          return ExpansionTile(
                            title: Text(contact.displayName),
                            children:
                                phoneList.map((phoneNumber) {
                                  final normalizedNumber = phoneNumber
                                      .replaceAll(RegExp(r'[^\d+]'), '');

                                  final isSelected = selectedNumbers.any((num) {
                                    String n = num.replaceAll(
                                      RegExp(r'[^\d+]'),
                                      '',
                                    );
                                    return n == normalizedNumber;
                                  });

                                  return CheckboxListTile(
                                    title: Text(phoneNumber),
                                    value: isSelected,
                                    onChanged: (val) {
                                      setModalState(() {
                                        if (val == true) {
                                          // إضافة إذا غير موجود
                                          if (!selectedNumbers.any((num) {
                                            String n = num.replaceAll(
                                              RegExp(r'[^\d+]'),
                                              '',
                                            );
                                            return n == normalizedNumber;
                                          })) {
                                            selectedNumbers.add(phoneNumber);
                                          }
                                        } else {
                                          selectedNumbers.removeWhere((num) {
                                            String n = num.replaceAll(
                                              RegExp(r'[^\d+]'),
                                              '',
                                            );
                                            return n == normalizedNumber;
                                          });
                                        }
                                      });
                                    },
                                  );
                                }).toList(),
                          );
                        },
                      ),
                    ),
                    const SizedBox(height: 16),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton(
                            onPressed: () async {
                              await _saveCallPhoneNumbers(selectedNumbers);
                              Navigator.pop(context);
                              _showSnackBar('تم حفظ أرقام المكالمات');
                            },
                            child: const Text("حفظ"),
                          ),
                        ),
                        const SizedBox(width: 16),
                        Expanded(
                          child: OutlinedButton(
                            onPressed: () => Navigator.pop(context),
                            child: const Text("إلغاء"),
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 16),
                  ],
                ),
              );
            },
          ),
    );
  }

  // ======== حوار تعديل جهة الاتصال لتصفية الرسائل (رقم وحيد) =======
  void _showContactEditDialog() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder:
          (context) => FutureBuilder<bool>(
            future: _requestContactPermissionAndLoad(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const Center(child: CircularProgressIndicator());
              }
              if (snapshot.hasError || snapshot.data != true) {
                return Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Icon(
                        Icons.contact_support_outlined,
                        size: 48,
                        color: Colors.grey,
                      ),
                      const SizedBox(height: 16),
                      Text(
                        "لم يتم منح إذن الوصول لجهات الاتصال",
                        style: Theme.of(context).textTheme.titleMedium
                            ?.copyWith(fontWeight: FontWeight.bold),
                        textAlign: TextAlign.center,
                      ),
                      const SizedBox(height: 8),
                      Text(
                        "يرجى منح إذن الوصول لجهات الاتصال من إعدادات التطبيق",
                        textAlign: TextAlign.center,
                      ),
                      const SizedBox(height: 16),
                      ElevatedButton.icon(
                        onPressed: () => openAppSettings(),
                        icon: const Icon(Icons.settings),
                        label: const Text("فتح الإعدادات"),
                        style: ElevatedButton.styleFrom(
                          backgroundColor:
                              Theme.of(context).colorScheme.surface,
                          foregroundColor:
                              Theme.of(context).colorScheme.primary,
                        ),
                      ),
                    ],
                  ),
                );
              }
              return FutureBuilder<List<Contact>>(
                future: _loadAllContacts(),
                builder: (context, contactsSnapshot) {
                  if (contactsSnapshot.connectionState ==
                      ConnectionState.waiting) {
                    return const Center(child: CircularProgressIndicator());
                  }
                  if (!contactsSnapshot.hasData ||
                      contactsSnapshot.data!.isEmpty) {
                    return Center(
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          const Icon(
                            Icons.contacts_outlined,
                            size: 48,
                            color: Colors.grey,
                          ),
                          const SizedBox(height: 16),
                          Text(
                            "لا توجد جهات اتصال",
                            style: Theme.of(context).textTheme.titleMedium,
                          ),
                        ],
                      ),
                    );
                  }
                  final contacts = contactsSnapshot.data!;
                  return StatefulBuilder(
                    builder: (context, setModalState) {
                      return Padding(
                        padding: EdgeInsets.only(
                          bottom: MediaQuery.of(context).viewInsets.bottom,
                          left: 16,
                          right: 16,
                          top: 24,
                        ),
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Row(
                              children: [
                                IconButton(
                                  icon: const Icon(Icons.search),
                                  onPressed: () {},
                                ),
                                Expanded(
                                  child: Text(
                                    "اختر جهة الاتصال لتصفية الرسائل",
                                    style: Theme.of(context)
                                        .textTheme
                                        .titleLarge
                                        ?.copyWith(fontWeight: FontWeight.bold),
                                    textAlign: TextAlign.center,
                                  ),
                                ),
                                IconButton(
                                  icon: const Icon(Icons.close),
                                  onPressed: () => Navigator.pop(context),
                                ),
                              ],
                            ),
                            const SizedBox(height: 16),
                            Expanded(
                              child: ListView.builder(
                                shrinkWrap: true,
                                itemCount: contacts.length,
                                itemBuilder: (context, index) {
                                  final contact = contacts[index];
                                  final phone =
                                      contact.phones.isNotEmpty
                                          ? contact.phones.first.number
                                          : "";
                                  return Card(
                                    margin: const EdgeInsets.symmetric(
                                      vertical: 4,
                                    ),
                                    child: ListTile(
                                      leading: CircleAvatar(
                                        backgroundColor: Theme.of(
                                          context,
                                        ).colorScheme.primary.withOpacity(0.1),
                                        child: Icon(
                                          Icons.person,
                                          color:
                                              Theme.of(
                                                context,
                                              ).colorScheme.primary,
                                        ),
                                      ),
                                      title: Text(
                                        contact.displayName,
                                        style: const TextStyle(
                                          fontWeight: FontWeight.w500,
                                        ),
                                      ),
                                      subtitle:
                                          phone.isNotEmpty ? Text(phone) : null,
                                      trailing:
                                          phone.isNotEmpty
                                              ? Icon(
                                                Icons.arrow_forward_ios,
                                                size: 16,
                                                color: Theme.of(context)
                                                    .colorScheme
                                                    .onSurface
                                                    .withOpacity(0.5),
                                              )
                                              : null,
                                      onTap:
                                          phone.isNotEmpty
                                              ? () async {
                                                await _saveMessageContact(
                                                  phone,
                                                );
                                                Navigator.pop(context);
                                              }
                                              : null,
                                    ),
                                  );
                                },
                              ),
                            ),
                            const SizedBox(height: 16),
                            OutlinedButton(
                              onPressed: Navigator.of(context).pop,
                              child: const Text("إلغاء"),
                            ),
                            const SizedBox(height: 16),
                          ],
                        ),
                      );
                    },
                  );
                },
              );
            },
          ),
    );
  }

  Future<bool> _requestContactPermissionAndLoad() async {
    final status = await Permission.contacts.status;
    if (!status.isGranted) {
      final result = await Permission.contacts.request();
      return result.isGranted;
    }
    return true;
  }

  Future<List<Contact>> _loadAllContacts() async {
    final permissionStatus = await Permission.contacts.status;
    if (!permissionStatus.isGranted) {
      final result = await Permission.contacts.request();
      if (!result.isGranted) {
        throw Exception("لم يتم منح إذن الوصول لجهات الاتصال");
      }
    }
    return FlutterContacts.getContacts(
      withProperties: true,
      withThumbnail: false,
    );
  }

  // ======== أزرار واجهة المستخدم ============
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          _savedContact != null
              ? "رسائل ${_savedContact!.length > 15 ? '${_savedContact!.substring(0, 15)}...' : _savedContact}"
              : "الرئيسية",
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.edit_note),
            onPressed: _showContactEditDialog,
            tooltip: "تعديل جهة اتصال الرسائل",
          ),
          IconButton(
            icon: const Icon(Icons.contact_phone),
            onPressed: _showPhoneNumbersSelectionDialog,
            tooltip: "إدارة أرقام المكالمات",
          ),
          if (_savedTextPattern != null || _savedContact != null)
            IconButton(
              icon: const Icon(Icons.filter_list_alt),
              onPressed: _showTextPatternSettingsDialog,
              tooltip: "إعدادات النص",
            ),
        ],
      ),
      body: _buildBody(),
      floatingActionButton:
          _callPhoneNumbers.isNotEmpty ? _buildCallButton() : null,
    );
  }

  Widget _buildBody() {
    if (_isLoading) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const CircularProgressIndicator(),
            const SizedBox(height: 16),
            Text(
              "جاري تحميل الرسائل...",
              style: Theme.of(context).textTheme.titleMedium,
            ),
          ],
        ),
      );
    }

    if (_savedContact == null) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.sms_outlined,
                size: 80,
                color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
              ),
              const SizedBox(height: 24),
              Text(
                "لم يتم تحديد جهة اتصال لتصفية الرسائل",
                style: Theme.of(
                  context,
                ).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),
              ElevatedButton.icon(
                onPressed: _showContactEditDialog,
                icon: const Icon(Icons.add_circle_outline),
                label: const Text("إضافة جهة اتصال لتصفية الرسائل"),
              ),
            ],
          ),
        ),
      );
    }

    if (_messages.isEmpty) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.inbox_outlined,
                size: 80,
                color: Theme.of(
                  context,
                ).colorScheme.onBackground.withOpacity(0.3),
              ),
              const SizedBox(height: 24),
              Text(
                _savedTextPattern != null && _savedTextPattern!.isNotEmpty
                    ? "لا توجد رسائل غير مقروءة تطابق النص المحدد"
                    : "لا توجد رسائل غير مقروءة",
                style: Theme.of(
                  context,
                ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),
              Text(
                "سيتم عرض الرسائل الجديدة تلقائيًا عند وصولها",
                textAlign: TextAlign.center,
                style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                  color: Theme.of(
                    context,
                  ).colorScheme.onBackground.withOpacity(0.6),
                ),
              ),
            ],
          ),
        ),
      );
    }

    return RefreshIndicator(
      onRefresh: _loadMessagesAutomatically,
      color: Theme.of(context).colorScheme.primary,
      child: ListView.builder(
        padding: const EdgeInsets.all(8),
        itemCount: _messages.length,
        itemBuilder: (context, index) {
          final msg = _messages[index];
          final similarity =
              (_savedTextPattern != null && _savedTextPattern!.isNotEmpty)
                  ? partialRatio(
                    (msg.body ?? '').toLowerCase(),
                    _savedTextPattern!.toLowerCase(),
                  )
                  : 100;

          return Card(
            margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
            child: InkWell(
              borderRadius: BorderRadius.circular(16),
              onTap: () {},
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Container(
                          width: 40,
                          height: 40,
                          decoration: BoxDecoration(
                            color: Theme.of(
                              context,
                            ).colorScheme.primary.withOpacity(0.1),
                            shape: BoxShape.circle,
                          ),
                          child: Icon(
                            Icons.sms_outlined,
                            color: Theme.of(context).colorScheme.primary,
                          ),
                        ),
                        const SizedBox(width: 12),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              FutureBuilder<String?>(
                                future: getContactNameFromNumber(msg.address),
                                builder: (context, snapshot) {
                                  final name =
                                      snapshot.data ??
                                      msg.address ??
                                      "غير معروف";
                                  return Text(
                                    name,
                                    style: const TextStyle(
                                      fontWeight: FontWeight.bold,
                                      fontSize: 16,
                                    ),
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                  );
                                },
                              ),
                              const SizedBox(height: 4),
                              Text(
                                msg.body ?? "لا يوجد محتوى",
                                style: TextStyle(
                                  color: Theme.of(
                                    context,
                                  ).colorScheme.onBackground.withOpacity(0.8),
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 12),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          _formatDate(msg.date),
                          style: TextStyle(
                            fontSize: 12,
                            color: Theme.of(
                              context,
                            ).colorScheme.onBackground.withOpacity(0.6),
                          ),
                        ),
                        if (_savedTextPattern != null &&
                            _savedTextPattern!.isNotEmpty)
                          Chip(
                            label: Text(
                              "${similarity.toStringAsFixed(0)}%",
                              style: TextStyle(
                                color: _getSimilarityColor(
                                  similarity as double,
                                ),
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            backgroundColor: _getSimilarityColor(
                              similarity as double,
                            ).withOpacity(0.1),
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8),
                            ),
                            side: BorderSide(
                              color: _getSimilarityColor(
                                similarity as double,
                              ).withOpacity(0.3),
                            ),
                          ),
                      ],
                    ),
                    if (_savedTextPattern != null &&
                        _savedTextPattern!.isNotEmpty)
                      Padding(
                        padding: const EdgeInsets.only(top: 8),
                        child: LinearProgressIndicator(
                          value: similarity / 100,
                          backgroundColor: Colors.grey.shade200,
                          color: _getSimilarityColor(similarity as double),
                          minHeight: 4,
                          borderRadius: BorderRadius.circular(2),
                        ),
                      ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }

  Color _getSimilarityColor(double similarity) {
    if (similarity >= 80)
      return Colors.green;
    else if (similarity >= 50)
      return Colors.orange;
    else
      return Colors.red;
  }

  Widget _buildCallButton() {
    if (_isCalling) {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          FloatingActionButton(
            onPressed: _stopCallSequence,
            backgroundColor: Colors.red,
            child: const Icon(Icons.stop),
          ),
          const SizedBox(height: 16),
          StreamBuilder<int>(
            stream: _callProgressController.stream,
            builder: (context, snapshot) {
              return Chip(
                label: Text(
                  "جاري الاتصال ${snapshot.data ?? 0}/${_callPhoneNumbers.length}",
                  style: const TextStyle(color: Colors.white),
                ),
                backgroundColor: Theme.of(context).colorScheme.primary,
              );
            },
          ),
        ],
      );
    } else {
      return FloatingActionButton.extended(
        onPressed: _callPhoneNumbers.isNotEmpty ? _startCallSequence : null,
        icon: const Icon(Icons.phone_outlined),
        label: const Text("إجراء مكالمات"),
        backgroundColor:
            _callPhoneNumbers.isEmpty
                ? Colors.grey
                : Theme.of(context).colorScheme.primary,
      );
    }
  }

  // تعديل عملية الاستدعاء لتكون متسلسلة تلقائية بدون تداخل مع الكود السابق
  Future<void> _startCallSequence() async {
    if (_callPhoneNumbers.isEmpty) {
      _showSnackBar("لا توجد أرقام للاتصال بها");
      return;
    }

    if (!await _checkAndRequestCallPermission()) {
      return;
    }

    setState(() {
      _isCalling = true;
      _currentCallIndex = 0;
    });

    _callProgressController.add(0);

    for (int i = 0; i < _callPhoneNumbers.length && _isCalling; i++) {
      _currentCallIndex = i;
      _callProgressController.add(i + 1);
      final number = _callPhoneNumbers[i];

      _showSnackBar(
        "جاري الاتصال بالرقم: $number (${i + 1}/${_callPhoneNumbers.length})",
      );

      try {
        await _makePhoneCall(number);

        // انتظار وقت معقول قبل الاتصال التالي (مثلاً 30 ثانية)
        // لأن الاتصال الخارجي يفتح تطبيق الهاتف ولا يمكننا معرفة اكتماله بالضبط
        // لذا وضعنا تأخير ثابت
        if (i < _callPhoneNumbers.length - 1 && _isCalling) {
          await Future.delayed(Duration(seconds: 30));
        }
      } catch (e) {
        _handleCallError(number, e);
      }
    }

    _completeCallSequence();
  }

  Future<bool> _checkAndRequestCallPermission() async {
    if (!await Permission.phone.isGranted) {
      final status = await Permission.phone.request();
      if (!status.isGranted) {
        _showSnackBar("يجب منح إذن الاتصال لاستخدام هذه الميزة");
        return false;
      }
    }
    return true;
  }

  Future<void> _makePhoneCall(String number) async {
    try {
      final Uri launchUri = Uri.parse('tel:$number');
      await launchUrl(launchUri);

      _logCall(number, true);
      debugPrint("تم بدء الاتصال بالرقم: $number");
    } catch (e) {
      _logCall(number, false, e.toString());
      throw e;
    }
  }

  void _completeCallSequence() {
    if (mounted) {
      setState(() {
        _isCalling = false;
      });

      if (_currentCallIndex >= _callPhoneNumbers.length - 1) {
        _showSnackBar("تم الانتهاء من جميع الاتصالات");
      }

      _callProgressController.add(0);
    }
  }

  void _stopCallSequence() {
    if (mounted) {
      setState(() {
        _isCalling = false;
      });
      _showSnackBar("تم إيقاف سلسلة المكالمات");
      _callProgressController.add(0);
    }
  }

  void _handleCallError(String number, dynamic error) {
    _logCall(number, false, error.toString());
    _showSnackBar("فشل الاتصال بالرقم $number: ${error.toString()}");
  }

  void _logCall(String number, bool success, [String? error]) {
    _callLogs.add({
      'number': number,
      'timestamp': DateTime.now(),
      'success': success,
      'error': error,
    });
  }

  // ======= إعدادات فلترة نص الرسائل =======
  void _showTextPatternSettingsDialog() {
    final textPatternController = TextEditingController(
      text: _savedTextPattern ?? '',
    );
    bool usePartial = _usePartialMatch;
    double threshold = _similarityThreshold;

    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder:
          (context) => StatefulBuilder(
            builder: (context, setModalState) {
              return Padding(
                padding: EdgeInsets.only(
                  bottom: MediaQuery.of(context).viewInsets.bottom,
                  left: 16,
                  right: 16,
                  top: 24,
                ),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Row(
                      children: [
                        IconButton(
                          icon: const Icon(Icons.close),
                          onPressed: () => Navigator.pop(context),
                        ),
                        Expanded(
                          child: Text(
                            "إعدادات تصفية الرسائل",
                            style: Theme.of(context).textTheme.titleLarge
                                ?.copyWith(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.center,
                          ),
                        ),
                        const SizedBox(width: 48),
                      ],
                    ),
                    const SizedBox(height: 16),
                    TextField(
                      controller: textPatternController,
                      maxLines: 3,
                      decoration: InputDecoration(
                        labelText: 'النص للبحث عنه',
                        hintText: 'اتركه فارغًا لعرض جميع الرسائل',
                        prefixIcon: Icon(
                          Icons.text_fields_outlined,
                          color: Theme.of(context).colorScheme.primary,
                        ),
                      ),
                    ),
                    const SizedBox(height: 16),
                    SwitchListTile(
                      contentPadding: EdgeInsets.zero,
                      title: const Text("مطابقة جزئية للنص"),
                      subtitle: Text(
                        usePartial
                            ? "مفعلة - البحث عن تشابه في النص"
                            : "معطلة - البحث عن تطابق كامل",
                        style: TextStyle(
                          color: Theme.of(
                            context,
                          ).colorScheme.onBackground.withOpacity(0.6),
                          fontSize: 12,
                        ),
                      ),
                      secondary: Icon(
                        usePartial ? Icons.check : Icons.text_fields,
                        color: Theme.of(context).colorScheme.primary,
                      ),
                      value: usePartial,
                      onChanged:
                          (value) => setModalState(() => usePartial = value),
                    ),
                    const SizedBox(height: 8),
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Row(
                            children: [
                              Icon(
                                Icons.speed_outlined,
                                size: 20,
                                color: Theme.of(
                                  context,
                                ).colorScheme.onBackground.withOpacity(0.8),
                              ),
                              const SizedBox(width: 8),
                              Text(
                                "حساسية المطابقة: ${(threshold * 100).toStringAsFixed(0)}%",
                                style: TextStyle(
                                  color: Theme.of(
                                    context,
                                  ).colorScheme.onBackground.withOpacity(0.8),
                                ),
                              ),
                            ],
                          ),
                          const SizedBox(height: 4),
                          Slider(
                            value: threshold,
                            min: 0.5,
                            max: 1.0,
                            divisions: 5,
                            onChanged:
                                (value) =>
                                    setModalState(() => threshold = value),
                          ),
                        ],
                      ),
                    ),
                    const SizedBox(height: 16),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton(
                            onPressed: () {
                              _saveTextFilterSettings(
                                textPatternController.text.trim(),
                                usePartial,
                                threshold,
                              );
                              Navigator.pop(context);
                            },
                            child: const Text("حفظ الإعدادات"),
                          ),
                        ),
                        const SizedBox(width: 16),
                        Expanded(
                          child: OutlinedButton(
                            onPressed: () => Navigator.pop(context),
                            child: const Text("إلغاء"),
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 16),
                  ],
                ),
              );
            },
          ),
    );
  }

  Future<void> _saveTextFilterSettings(
    String textPattern,
    bool usePartial,
    double threshold,
  ) async {
    await _prefs?.setString('savedTextPattern', textPattern);
    await _prefs?.setBool('usePartialMatch', usePartial);
    await _prefs?.setDouble('similarityThreshold', threshold);
    setState(() {
      _savedTextPattern = textPattern;
      _usePartialMatch = usePartial;
      _similarityThreshold = threshold;
      _messages.clear();
    });
    await _loadMessagesAutomatically();
  }

  // ======= تنسيقات وغيرها ========
  String _formatDate(int? timestamp) {
    if (timestamp == null) return "غير معروف";

    final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
    final day = date.day.toString().padLeft(2, '0');
    final month = date.month.toString().padLeft(2, '0');
    final hour = date.hour.toString().padLeft(2, '0');
    final minute = date.minute.toString().padLeft(2, '0');

    return "$day/$month/${date.year} - $hour:$minute";
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            const Icon(Icons.info_outline, color: Colors.white),
            const SizedBox(width: 8),
            Expanded(child: Text(message)),
          ],
        ),
        duration: const Duration(seconds: 3),
        behavior: SnackBarBehavior.floating,
        margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      ),
    );
  }
}

اريد الكود الكامل لاقوم باستخدامة مباشرة