import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:async';
import '../../../services/firestore_service.dart';
import '../../../services/realtime_database_service.dart';
import '../../../models/patient_model.dart';
import '../../../models/chart_data_point.dart';
import '../../../models/history_model.dart';
import '../../../models/notification_model.dart';
import '../../../models/realtime_monitoring_model.dart';
import '../../../widgets/app_snackbar.dart';

class InfusData {
  final String dropsPerMinute;
  final String room;
  final String deviceId;
  final String updateTime;
  final String deviceStatus;

  InfusData({
    required this.dropsPerMinute,
    required this.room,
    required this.deviceId,
    required this.updateTime,
    required this.deviceStatus,
  });
}

class NotificationData {
  final String id;
  final String title;
  final String message;
  final String room;
  final String deviceId;
  final String timeAgo;
  final DateTime createdAt;

  NotificationData({
    required this.id,
    required this.title,
    required this.message,
    required this.room,
    required this.deviceId,
    required this.timeAgo,
    required this.createdAt,
  });
}

class HomePatientController extends GetxController {
  final FirestoreService _firestoreService = FirestoreService();
  final RealtimeDatabaseService _realtimeService = RealtimeDatabaseService();

  final deviceId = ''.obs;
  final roomId = ''.obs;
  final patientName = 'Patient'.obs;
  final userEmail = ''.obs;

  final currentCarouselIndex = 0.obs;
  final bannerImages = [
    'assets/images/banner-slider3.png',
    'assets/images/banner-slider4.png',
  ];

  final currentInfusData = InfusData(
    dropsPerMinute: '0',
    room: '-',
    deviceId: '-',
    updateTime: '-',
    deviceStatus: 'disconnected',
  ).obs;

  final chartDataPoints = <ChartDataPoint>[].obs;
  final notificationsList = <NotificationData>[].obs;

  final isLoading = true.obs;
  final isLoadingHistory = true.obs;
  final isLoadingNotifications = true.obs;

  StreamSubscription? _realtimeSubscription;
  StreamSubscription? _notificationsSubscription;
  StreamSubscription? _historySubscription;

  @override
  void onInit() {
    super.onInit();
    _loadDataFromArguments();
  }

  @override
  void onReady() {
    super.onReady();
  }

  @override
  void onClose() {
    _realtimeSubscription?.cancel();
    _notificationsSubscription?.cancel();
    _historySubscription?.cancel();
    super.onClose();
  }

  void _loadDataFromArguments() async {
    try {
      final args = Get.arguments as Map<String, dynamic>?;

      if (args != null) {
        deviceId.value = args['deviceId'] ?? '';
        patientName.value = args['userName'] ?? 'Patient';
        userEmail.value = args['userEmail'] ?? '';
      }

      if (deviceId.value.isEmpty) {
        AppSnackbar.error('Device ID tidak ditemukan');
        isLoading.value = false;
        return;
      }

      await _loadPatientData();

      if (roomId.value.isNotEmpty) {
        _startRealtimeMonitoring();
        _loadHistoryData();
        _loadNotifications();
      } else {
        AppSnackbar.error('Room ID tidak ditemukan');
        isLoading.value = false;
      }
    } catch (e) {
      AppSnackbar.error('Gagal memuat data: $e');
      isLoading.value = false;
    }
  }

  Future<void> _loadPatientData() async {
    try {
      isLoading.value = true;

      final patient = await _firestoreService.getPatientByDeviceId(
        deviceId.value,
      );

      if (patient != null) {
        patientName.value = patient.namePatient;
        roomId.value = patient.roomId;

        final room = await _firestoreService.getRoomById(patient.roomId);

        if (currentInfusData.value.deviceStatus == 'disconnected') {
          currentInfusData.value = InfusData(
            dropsPerMinute: '0',
            room: room?.roomName ?? patient.roomId,
            deviceId: patient.deviceId,
            updateTime: 'Loading...',
            deviceStatus: 'disconnected',
          );
        }
      } else {
        AppSnackbar.error('Data pasien tidak ditemukan');
      }
    } catch (e) {
      AppSnackbar.error('Gagal memuat data pasien: $e');
      print('Error loading patient data: $e');
    } finally {
      isLoading.value = false;
    }
  }

  void _startRealtimeMonitoring() {
    try {
      if (roomId.value.isEmpty || deviceId.value.isEmpty) {
        print('Room ID or Device ID is empty');
        return;
      }

      final dbRoomId = roomId.value.toLowerCase().replaceAll(' ', '_');

      _realtimeSubscription?.cancel(); // Cancel previous subscription if exists

      _realtimeSubscription = _realtimeService
          .getDeviceStream(dbRoomId, deviceId.value)
          .listen(
            (device) {
              if (device != null) {
                _updateCurrentInfusData(device);
              } else {
                print('Received null device data');
              }
            },
            onError: (error) {
              print('Realtime stream error: $error');
              AppSnackbar.error('Koneksi realtime terputus');
            },
            cancelOnError: false,
          );
    } catch (e) {
      print('Error starting monitoring: $e');
      AppSnackbar.error('Gagal memulai monitoring: $e');
    }
  }

  void _updateCurrentInfusData(RealtimeMonitoringModel device) async {
    try {
      final room = await _firestoreService.getRoomById(device.roomId);

      currentInfusData.value = InfusData(
        dropsPerMinute: '${device.dropRate.toStringAsFixed(0)}',
        room: room?.roomName ?? device.roomId,
        deviceId: device.deviceId,
        updateTime: _getLastUpdateText(device.lastUpdate),
        deviceStatus: device.deviceStatus,
      );
    } catch (e) {
      print('Error updating infus data: $e');
      AppSnackbar.error('Gagal update data: $e');
    }
  }

  void _loadHistoryData() {
    try {
      isLoadingHistory.value = true;

      _historySubscription?.cancel(); // Cancel previous subscription if exists

      _historySubscription = _firestoreService
          .getDeviceHistoriesStream(deviceId.value)
          .listen(
            (histories) {
              try {
                if (histories.isNotEmpty) {
                  _processHistoryData(histories);
                } else {
                  chartDataPoints.value = [];
                }
                isLoadingHistory.value = false;
              } catch (e) {
                print('Error processing history: $e');
                chartDataPoints.value = [];
                isLoadingHistory.value = false;
              }
            },
            onError: (error) {
              print('History stream error: $error');
              chartDataPoints.value = [];
              isLoadingHistory.value = false;
              AppSnackbar.error('Gagal memuat history: $error');
            },
            cancelOnError: false,
          );
    } catch (e) {
      print('Error loading history: $e');
      isLoadingHistory.value = false;
      AppSnackbar.error('Gagal memuat history: $e');
    }
  }

  void _processHistoryData(List<HistoryModel> histories) {
    try {
      histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));
      final latestHistories = histories.take(10).toList();
      latestHistories.sort((a, b) => a.timestamp.compareTo(b.timestamp));
      final List<ChartDataPoint> points = latestHistories.map((history) {
        return ChartDataPoint(
          hour: history.timestamp.hour,
          dropsPerMinute: history.dropPerMinute,
        );
      }).toList();

      chartDataPoints.value = points;
    } catch (e) {
      print('Error processing history data: $e');
      chartDataPoints.value = [];
    }
  }

  void _loadNotifications() {
    try {
      isLoadingNotifications.value = true;

      _notificationsSubscription
          ?.cancel(); // Cancel previous subscription if exists

      _notificationsSubscription = _firestoreService
          .getNotificationsStream()
          .listen(
            (notifications) async {
              try {
                final filteredNotifications = notifications
                    .where((n) => n.deviceId == deviceId.value)
                    .toList();

                final List<NotificationData> notifList = [];

                for (var notif in filteredNotifications) {
                  try {
                    final patient = await _firestoreService
                        .getPatientByDeviceId(notif.deviceId);
                    final room = patient != null
                        ? await _firestoreService.getRoomById(patient.roomId)
                        : null;

                    notifList.add(
                      NotificationData(
                        id: notif.id,
                        title: notif.title,
                        message: notif.message,
                        room: room?.roomName ?? '-',
                        deviceId: notif.deviceId,
                        timeAgo: _getLastUpdateText(notif.createdAt),
                        createdAt: notif.createdAt,
                      ),
                    );
                  } catch (e) {
                    print('Error processing notification ${notif.id}: $e');
                    // Continue with other notifications
                  }
                }

                notifList.sort((a, b) => b.createdAt.compareTo(a.createdAt));

                notificationsList.value = notifList;
                isLoadingNotifications.value = false;
              } catch (e) {
                print('Error processing notifications: $e');
                isLoadingNotifications.value = false;
              }
            },
            onError: (error) {
              print('Notifications stream error: $error');
              isLoadingNotifications.value = false;
              AppSnackbar.error('Gagal memuat notifikasi: $error');
            },
            cancelOnError: false,
          );
    } catch (e) {
      print('Error loading notifications: $e');
      isLoadingNotifications.value = false;
      AppSnackbar.error('Gagal memuat notifikasi: $e');
    }
  }

  void updateCarouselIndex(int index) {
    currentCarouselIndex.value = index;
  }

  void showCallDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15),
          ),
          title: const Text(
            'Hubungi Perawat',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          content: const Text(
            'Apakah Anda ingin menghubungi perawat melalui WhatsApp?',
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: Text('Batal', style: TextStyle(color: Colors.grey[600])),
            ),
            ElevatedButton(
              onPressed: () async {
                Navigator.of(context).pop();
                await _openWhatsApp();
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(
                  0xFF25D366,
                ), // WhatsApp green color
                foregroundColor: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(8),
                ),
              ),
              child: const Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.phone, size: 18),
                  SizedBox(width: 8),
                  Text('Hubungi'),
                ],
              ),
            ),
          ],
        );
      },
    );
  }

  Future<void> _openWhatsApp() async {
    try {
      const String nursePhoneNumber =
          '6281234567890'; 

      final String message = Uri.encodeComponent(
        'Halo, saya ${patientName.value} di ruangan ${currentInfusData.value.room}. '
        'Saya membutuhkan bantuan perawat untuk device ${deviceId.value}.',
      );

      final String whatsappUrl =
          'https://wa.me/$nursePhoneNumber?text=$message';

      if (await canLaunchUrl(Uri.parse(whatsappUrl))) {
        await launchUrl(
          Uri.parse(whatsappUrl),
          mode: LaunchMode.externalApplication,
        );
      } else {
        AppSnackbar.error('Tidak dapat membuka WhatsApp');
      }
    } catch (e) {
      print('Error opening WhatsApp: $e');
      AppSnackbar.error('Gagal menghubungi perawat: $e');
    }
  }

  void showLogoutDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          backgroundColor: Colors.white,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15),
          ),
          title: const Text(
            'Konfirmasi Logout',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
          ),
          content: const Text(
            'Yakin ingin keluar?',
            style: TextStyle(fontSize: 16),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              style: TextButton.styleFrom(
                foregroundColor: Colors.grey[600],
                padding: const EdgeInsets.symmetric(
                  vertical: 12,
                  horizontal: 20,
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(8),
                ),
              ),
              child: const Text('Batal'),
            ),
            ElevatedButton(
              onPressed: () async {
                Navigator.of(context).pop();
                try {
                  await FirebaseAuth.instance.signOut();
                  Get.offAllNamed('/login');
                } catch (e) {
                  print('Error logging out: $e');
                  AppSnackbar.error('Gagal logout: $e');
                }
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.red,
                foregroundColor: Colors.white,
                padding: const EdgeInsets.symmetric(
                  vertical: 12,
                  horizontal: 20,
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(8),
                ),
              ),
              child: const Text(
                'Logout',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ],
        );
      },
    );
  }

  String _getLastUpdateText(DateTime lastUpdate) {
    try {
      final difference = DateTime.now().difference(lastUpdate);
      if (difference.inMinutes < 1) {
        return 'Just now';
      } else if (difference.inMinutes < 60) {
        return '${difference.inMinutes}m ago';
      } else if (difference.inHours < 24) {
        return '${difference.inHours}h ago';
      } else {
        return '${difference.inDays}d ago';
      }
    } catch (e) {
      print('Error calculating time difference: $e');
      return 'Unknown';
    }
  }

  Future<void> refreshData() async {
    try {
      await _loadPatientData();
      // Tidak perlu reload history karena sudah menggunakan stream
      // History akan auto-update
    } catch (e) {
      print('Error refreshing data: $e');
      AppSnackbar.error('Gagal refresh data: $e');
    }
  }
}
