import 'package:get/get.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_database/firebase_database.dart';
import '../../../services/firestore_service.dart';
import '../../../services/realtime_database_service.dart';
import '../../../models/patient_model.dart';
import '../../../models/device_model.dart';
import '../../../models/room_model.dart';
import '../../../widgets/app_snackbar.dart';

class Patient {
  final String id;
  final String name;
  final String room;
  final String deviceId;
  final String guardian;
  final String email;
  final String? userId;
  final String status;

  Patient({
    required this.id,
    required this.name,
    required this.room,
    required this.deviceId,
    required this.guardian,
    required this.email,
    this.userId,
    this.status = 'Aktif',
  });

  Map<String, dynamic> toFirestore() {
    return {
      'name_patient': name,
      'name_guardian': guardian,
      'device_id': deviceId,
      'room_id': room,
      'user_id': userId,
    };
  }

  factory Patient.fromFirestore(DocumentSnapshot doc) {
    final data = doc.data() as Map<String, dynamic>;
    return Patient(
      id: doc.id,
      name: data['name_patient'] ?? '',
      guardian: data['name_guardian'] ?? '',
      deviceId: data['device_id'] ?? '',
      room: data['room_id'] ?? '',
      email: '',
      userId: data['user_id'],
    );
  }
}

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

  final patients = <Patient>[].obs;
  final isLoading = false.obs;

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

  void refreshPatients() {
    _listenToPatients();
  }

  void _listenToPatients() {
    _firestoreService.getPatientsStream().listen((patientModels) async {
      final patientsWithEmail = <Patient>[];

      for (var model in patientModels) {
        try {
          final email = await _getGuardianEmail(model.nameGuardian);
          final roomName = await _getRoomName(model.roomId);

          patientsWithEmail.add(
            Patient(
              id: model.id,
              name: model.namePatient,
              guardian: model.nameGuardian,
              deviceId: model.deviceId,
              room: roomName,
              email: email,
              userId: null,
            ),
          );
        } catch (e) {
          continue;
        }
      }

      patients.value = patientsWithEmail;
    }, onError: (error) => AppSnackbar.error('Gagal memuat data'));
  }

  Future<String> _getGuardianEmail(String guardianName) async {
    try {
      final userDoc = await FirebaseFirestore.instance
          .collection('users')
          .where('role', isEqualTo: 'guardian')
          .where('name', isEqualTo: guardianName)
          .limit(1)
          .get();

      return userDoc.docs.isNotEmpty
          ? userDoc.docs.first.data()['email'] ?? ''
          : '';
    } catch (e) {
      return '';
    }
  }

  Future<String> _getRoomName(String roomId) async {
    try {
      final roomDoc = await FirebaseFirestore.instance
          .collection('rooms')
          .doc(roomId)
          .get();
      return roomDoc.data()?['room_name'] ?? roomId;
    } catch (e) {
      return roomId;
    }
  }

  Future<void> addPatient({
    required String patientName,
    required String guardianName,
    required String roomName,
    required String deviceId,
    required String email,
    required String password,
  }) async {
    try {
      isLoading.value = true;

      if (!await _validateNewPatient(email, deviceId)) return;

      final roomId = _generateRoomId(roomName);

      // PERBAIKAN: Tambahkan device_id saat create user
      final userId = await _firestoreService.createUser(
        email: email,
        password: password,
        name: guardianName,
        role: 'guardian',
        deviceId: deviceId, // ✅ TAMBAHKAN INI
      );

      if (userId == null) throw Exception('Gagal membuat user');

      await _ensureRoomExists(roomId, roomName);
      await _createDevice(deviceId, roomId);
      await _firestoreService.createPatient(
        PatientModel(
          id: '',
          namePatient: patientName,
          nameGuardian: guardianName,
          deviceId: deviceId,
          roomId: roomId,
        ),
      );

      await _realtimeService.updateDeviceStatus(roomId, deviceId, 'connected');
      await _createDeviceInRealtimeDB(roomId, deviceId);

      Get.back();
      AppSnackbar.success('Pasien berhasil ditambahkan');
    } catch (e) {
      AppSnackbar.error('Gagal menambahkan pasien: $e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<bool> _validateNewPatient(String email, String deviceId) async {
    if (await _firestoreService.userExists(email)) {
      AppSnackbar.warning('Email sudah terdaftar');
      return false;
    }

    if (await _firestoreService.deviceExists(deviceId)) {
      AppSnackbar.warning('Device ID sudah terdaftar');
      return false;
    }

    if (await _firestoreService.patientExistsByDevice(deviceId)) {
      AppSnackbar.warning('Device sudah digunakan');
      return false;
    }

    return true;
  }

  Future<void> updatePatient({
    required String patientId,
    required String patientName,
    required String guardianName,
    required String roomName,
    required String deviceId,
    required String email,
    String? newPassword,
  }) async {
    try {
      isLoading.value = true;

      final oldPatient = await _firestoreService.getPatientById(patientId);
      if (oldPatient == null) throw Exception('Pasien tidak ditemukan');

      final roomId = _generateRoomId(roomName);

      if (deviceId != oldPatient.deviceId) {
        if (await _firestoreService.deviceExists(deviceId)) {
          AppSnackbar.warning('Device ID sudah terdaftar');
          return;
        }
      }

      await _firestoreService.updatePatient(
        patientId,
        PatientModel(
          id: patientId,
          namePatient: patientName,
          nameGuardian: guardianName,
          deviceId: deviceId,
          roomId: roomId,
        ),
      );

      if (deviceId != oldPatient.deviceId || roomId != oldPatient.roomId) {
        await _updateDeviceAndRoom(oldPatient, deviceId, roomId);
      }

      await _ensureRoomExists(roomId, roomName);

      // PERBAIKAN: Update device_id di users collection jika device berubah
      if (deviceId != oldPatient.deviceId) {
        final userDoc = await _firestoreService.getUserByEmail(email);
        if (userDoc != null) {
          await _firestoreService.updateUser(
            uid: userDoc.id,
            name: guardianName,
            email: email,
            deviceId: deviceId, // ✅ UPDATE device_id
          );
        }
      }

      Get.back();
      AppSnackbar.success('Data berhasil diperbarui');
    } catch (e) {
      AppSnackbar.error('Gagal memperbarui data: $e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> _updateDeviceAndRoom(
    PatientModel oldPatient,
    String newDeviceId,
    String newRoomId,
  ) async {
    await _firestoreService.deleteDevice(oldPatient.deviceId);
    await _deleteDeviceFromRealtimeDB(oldPatient.roomId, oldPatient.deviceId);
    await _createDevice(newDeviceId, newRoomId);
    await _createDeviceInRealtimeDB(newRoomId, newDeviceId);
  }

  // PERBAIKAN LENGKAP: Hapus dari semua collection + Authentication
  Future<void> deletePatient(String patientId, {String? password}) async {
    try {
      isLoading.value = true;

      final patient = await _firestoreService.getPatientById(patientId);
      if (patient == null) throw Exception('Pasien tidak ditemukan');

      // 1. Hapus dari Realtime Database
      await _deleteDeviceFromRealtimeDB(patient.roomId, patient.deviceId);

      // 2. Hapus histories berdasarkan device_id
      await _firestoreService.deleteHistoriesByDevice(patient.deviceId);

      // 3. Hapus notifications berdasarkan device_id
      await _firestoreService.deleteNotificationsByDevice(patient.deviceId);

      // 4. Hapus schedules berdasarkan device_id
      await _firestoreService.deleteSchedulesByDevice(patient.deviceId);

      // 5. Hapus device dari Firestore
      await _firestoreService.deleteDevice(patient.deviceId);

      // 6. Cari user berdasarkan guardian name dan device_id
      final userDoc = await FirebaseFirestore.instance
          .collection('users')
          .where('role', isEqualTo: 'guardian')
          .where('name', isEqualTo: patient.nameGuardian)
          .where('device_id', isEqualTo: patient.deviceId)
          .limit(1)
          .get();

      if (userDoc.docs.isNotEmpty) {
        final userId = userDoc.docs.first.id;
        final userEmail = userDoc.docs.first.data()['email'] as String;

        // 7. Hapus dari collection users
        await _firestoreService.deleteUser(userId);

        // 8. Hapus dari Firebase Authentication
        // CATATAN: Memerlukan password untuk delete dari Authentication
        if (password != null && password.isNotEmpty) {
          await _firestoreService.deleteUserFromAuth(userEmail, password);
        } else {
          // Jika tidak ada password, tampilkan warning
          print(
            '⚠️ User tidak terhapus dari Authentication karena password tidak tersedia',
          );
          AppSnackbar.warning(
            'User terhapus dari database, tapi tidak dari Authentication. Hubungi admin untuk menghapus akun sepenuhnya.',
          );
        }
      }

      // 9. Hapus patient dari Firestore
      await _firestoreService.deletePatient(patientId);

      AppSnackbar.success('Pasien berhasil dihapus');
    } catch (e) {
      AppSnackbar.error('Gagal menghapus pasien: $e');
      print('❌ Delete patient error: $e');
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> _ensureRoomExists(String roomId, String roomName) async {
    if (!await _firestoreService.roomExists(roomId)) {
      await _firestoreService.createRoom(
        RoomModel(
          id: roomId,
          roomName: roomName,
          capacity: 10,
          createdAt: DateTime.now(),
        ),
      );
    }
  }

  Future<void> _createDevice(String deviceId, String roomId) async {
    await _firestoreService.createDevice(
      DeviceModel(
        idDevices: deviceId,
        roomId: roomId,
        devicesName: 'Infusion Device $deviceId',
      ),
    );
  }

  Future<void> _createDeviceInRealtimeDB(String roomId, String deviceId) async {
    final devicePath = 'realtime/rooms/$roomId/devices/$deviceId';
    await FirebaseDatabase.instance.ref().child(devicePath).set({
      'controlling': {
        'servo_open': false,
        'last_command': DateTime.now().toIso8601String(),
      },
      'monitoring': {
        'device_status': 'connected',
        'drop_rate': 0,
        'last_update': DateTime.now().toIso8601String(),
      },
      'settings': {'servo_angle_open': 90, 'servo_angle_close': 0},
    });
  }

  Future<void> _deleteDeviceFromRealtimeDB(
    String roomId,
    String deviceId,
  ) async {
    final devicePath = 'realtime/rooms/$roomId/devices/$deviceId';
    await FirebaseDatabase.instance.ref().child(devicePath).remove();
  }

  String _generateRoomId(String roomName) {
    return roomName
        .trim()
        .toLowerCase()
        .replaceAll(RegExp(r'[^a-z0-9]+'), '_')
        .replaceAll(RegExp(r'_+'), '_')
        .replaceAll(RegExp(r'^_|_$'), '');
  }
}
