import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../models/patient_model.dart';
import '../models/device_model.dart';
import '../models/room_model.dart';
import '../models/notification_model.dart';
import '../models/schedule_model.dart';
import '../models/history_model.dart';
import '../models/user_model.dart';

class FirestoreService {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // ==================== USER MANAGEMENT ====================

  Future<bool> userExists(String email) async {
    try {
      final snapshot = await _firestore
          .collection('users')
          .where('email', isEqualTo: email)
          .limit(1)
          .get();
      return snapshot.docs.isNotEmpty;
    } catch (e) {
      return false;
    }
  }

  Future<String?> createUser({
    required String email,
    required String password,
    required String name,
    required String role,
    String? deviceId,
  }) async {
    final userCredential = await _auth.createUserWithEmailAndPassword(
      email: email,
      password: password,
    );

    final uid = userCredential.user!.uid;

    await _firestore.collection('users').doc(uid).set({
      'email': email,
      'name': name,
      'role': role,
      if (deviceId != null) 'device_id': deviceId, // TAMBAH device_id
      'created_at': FieldValue.serverTimestamp(),
    });

    await _auth.signOut();
    return uid;
  }

  Future<void> updateUser({
    required String uid,
    required String name,
    String? email,
    String? deviceId,
  }) async {
    final updateData = {'name': name};
    if (email != null) updateData['email'] = email;
    if (deviceId != null)
      updateData['device_id'] = deviceId; // Support update device_id
    await _firestore.collection('users').doc(uid).update(updateData);
  }

  Future<void> deleteUser(String uid) async {
    await _firestore.collection('users').doc(uid).delete();
  }

  Future<void> deleteUserFromAuth(String email, String password) async {
    try {
      // Sign in temporary dengan user yang akan dihapus
      final userCredential = await _auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );

      // Hapus user dari Authentication
      await userCredential.user?.delete();

      // Sign out
      await _auth.signOut();
    } catch (e) {
      print('Error deleting user from auth: $e');
      // Jika gagal, ignore error (misalnya user sudah tidak ada)
    }
  }

  Future<DocumentSnapshot?> getUserByEmail(String email) async {
    try {
      final snapshot = await _firestore
          .collection('users')
          .where('email', isEqualTo: email)
          .limit(1)
          .get();
      return snapshot.docs.isNotEmpty ? snapshot.docs.first : null;
    } catch (e) {
      return null;
    }
  }

  Future<UserModel?> getUserModelByEmail(String email) async {
    try {
      final snapshot = await _firestore
          .collection('users')
          .where('email', isEqualTo: email)
          .limit(1)
          .get();
      return snapshot.docs.isNotEmpty
          ? UserModel.fromFirestore(snapshot.docs.first)
          : null;
    } catch (e) {
      return null;
    }
  }

  // ==================== DEVICE MANAGEMENT ====================

  Future<bool> deviceExists(String deviceId) async {
    try {
      final doc = await _firestore.collection('devices').doc(deviceId).get();
      return doc.exists;
    } catch (e) {
      return false;
    }
  }

  Future<bool> patientExistsByDevice(String deviceId) async {
    try {
      final snapshot = await _firestore
          .collection('patients')
          .where('device_id', isEqualTo: deviceId)
          .limit(1)
          .get();
      return snapshot.docs.isNotEmpty;
    } catch (e) {
      return false;
    }
  }

  Stream<List<DeviceModel>> getDevicesStream() {
    return _firestore
        .collection('devices')
        .snapshots()
        .map(
          (snapshot) => snapshot.docs
              .map((doc) => DeviceModel.fromFirestore(doc))
              .toList(),
        );
  }

  Future<DeviceModel?> getDeviceById(String deviceId) async {
    try {
      final doc = await _firestore.collection('devices').doc(deviceId).get();
      return doc.exists ? DeviceModel.fromFirestore(doc) : null;
    } catch (e) {
      return null;
    }
  }

  Future<void> createDevice(DeviceModel device) async {
    await _firestore
        .collection('devices')
        .doc(device.idDevices)
        .set(device.toFirestore());
  }

  Future<void> deleteDevice(String deviceId) async {
    await _firestore.collection('devices').doc(deviceId).delete();
  }

  // ==================== PATIENT MANAGEMENT ====================

  Stream<List<PatientModel>> getPatientsStream() {
    return _firestore
        .collection('patients')
        .snapshots()
        .map(
          (snapshot) => snapshot.docs
              .map((doc) => PatientModel.fromFirestore(doc))
              .toList(),
        );
  }

  Future<PatientModel?> getPatientById(String patientId) async {
    try {
      final doc = await _firestore.collection('patients').doc(patientId).get();
      return doc.exists ? PatientModel.fromFirestore(doc) : null;
    } catch (e) {
      return null;
    }
  }

  Future<PatientModel?> getPatientByDeviceId(String deviceId) async {
    try {
      final snapshot = await _firestore
          .collection('patients')
          .where('device_id', isEqualTo: deviceId)
          .limit(1)
          .get();
      return snapshot.docs.isNotEmpty
          ? PatientModel.fromFirestore(snapshot.docs.first)
          : null;
    } catch (e) {
      return null;
    }
  }

  Future<void> createPatient(PatientModel patient) async {
    await _firestore.collection('patients').add(patient.toFirestore());
  }

  Future<void> updatePatient(String patientId, PatientModel patient) async {
    await _firestore
        .collection('patients')
        .doc(patientId)
        .update(patient.toFirestore());
  }

  Future<void> deletePatient(String patientId) async {
    await _firestore.collection('patients').doc(patientId).delete();
  }

  // ==================== ROOM MANAGEMENT ====================

  Future<bool> roomExists(String roomId) async {
    try {
      final doc = await _firestore.collection('rooms').doc(roomId).get();
      return doc.exists;
    } catch (e) {
      return false;
    }
  }

  Stream<List<RoomModel>> getRoomsStream() {
    return _firestore
        .collection('rooms')
        .snapshots()
        .map(
          (snapshot) =>
              snapshot.docs.map((doc) => RoomModel.fromFirestore(doc)).toList(),
        );
  }

  Future<RoomModel?> getRoomById(String roomId) async {
    try {
      final doc = await _firestore.collection('rooms').doc(roomId).get();
      return doc.exists ? RoomModel.fromFirestore(doc) : null;
    } catch (e) {
      return null;
    }
  }

  Future<void> createRoom(RoomModel room) async {
    await _firestore.collection('rooms').doc(room.id).set(room.toFirestore());
  }

  Future<void> deleteRoom(String roomId) async {
    await _firestore.collection('rooms').doc(roomId).delete();
  }

  // ==================== HISTORY MANAGEMENT ====================

  Stream<List<HistoryModel>> getDeviceHistoriesStream(String deviceId) {
    return _firestore
        .collection('histories')
        .where('device_id', isEqualTo: deviceId)
        .snapshots()
        .map((snapshot) {
          final histories = snapshot.docs
              .map((doc) => HistoryModel.fromFirestore(doc))
              .toList();

          histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));

          return histories;
        });
  }

  Future<List<HistoryModel>> getDeviceHistories(
    String deviceId, {
    int limit = 100,
  }) async {
    try {
      final snapshot = await _firestore
          .collection('histories')
          .where('device_id', isEqualTo: deviceId)
          .get();

      final histories = snapshot.docs
          .map((doc) => HistoryModel.fromFirestore(doc))
          .toList();

      histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));

      return histories.take(limit).toList();
    } catch (e) {
      return [];
    }
  }

  Future<List<HistoryModel>> getDeviceHistoriesInRange(
    String deviceId,
    DateTime startDate,
    DateTime endDate,
  ) async {
    try {
      final snapshot = await _firestore
          .collection('histories')
          .where('device_id', isEqualTo: deviceId)
          .where('timestamp', isGreaterThanOrEqualTo: startDate)
          .where('timestamp', isLessThanOrEqualTo: endDate)
          .get();

      final histories = snapshot.docs
          .map((doc) => HistoryModel.fromFirestore(doc))
          .toList();

      histories.sort((a, b) => b.timestamp.compareTo(a.timestamp));

      return histories;
    } catch (e) {
      return [];
    }
  }

  Future<List<HistoryModel>> getDeviceHistoriesToday(String deviceId) async {
    final now = DateTime.now();
    final startOfDay = DateTime(now.year, now.month, now.day);
    final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59);
    return getDeviceHistoriesInRange(deviceId, startOfDay, endOfDay);
  }

  Future<void> addHistory(HistoryModel history) async {
    await _firestore.collection('histories').add(history.toFirestore());
  }

  Future<void> deleteOldHistories({int daysToKeep = 30}) async {
    final cutoffDate = DateTime.now().subtract(Duration(days: daysToKeep));
    final snapshot = await _firestore
        .collection('histories')
        .where('timestamp', isLessThan: cutoffDate)
        .get();

    final batch = _firestore.batch();
    for (var doc in snapshot.docs) {
      batch.delete(doc.reference);
    }
    await batch.commit();
  }

  // BARU: Hapus semua histories berdasarkan device_id
  Future<void> deleteHistoriesByDevice(String deviceId) async {
    final snapshot = await _firestore
        .collection('histories')
        .where('device_id', isEqualTo: deviceId)
        .get();

    final batch = _firestore.batch();
    for (var doc in snapshot.docs) {
      batch.delete(doc.reference);
    }
    await batch.commit();
  }

  // ==================== NOTIFICATION MANAGEMENT ====================

  Stream<List<NotificationModel>> getNotificationsStream() {
    return _firestore
        .collection('notifications')
        .orderBy('created_at', descending: true)
        .snapshots()
        .map(
          (snapshot) => snapshot.docs
              .map((doc) => NotificationModel.fromFirestore(doc))
              .toList(),
        );
  }

  Future<void> addNotification(NotificationModel notification) async {
    await _firestore
        .collection('notifications')
        .add(notification.toFirestore());
  }

  Future<void> markNotificationAsRead(String notificationId) async {
    await _firestore.collection('notifications').doc(notificationId).update({
      'is_read': true,
    });
  }

  Future<void> deleteNotification(String notificationId) async {
    await _firestore.collection('notifications').doc(notificationId).delete();
  }

  // BARU: Hapus semua notifications berdasarkan device_id
  Future<void> deleteNotificationsByDevice(String deviceId) async {
    final snapshot = await _firestore
        .collection('notifications')
        .where('device_id', isEqualTo: deviceId)
        .get();

    final batch = _firestore.batch();
    for (var doc in snapshot.docs) {
      batch.delete(doc.reference);
    }
    await batch.commit();
  }

  // ==================== SCHEDULE MANAGEMENT ====================

  Stream<List<ScheduleModel>> getSchedulesStream({
    DateTime? date,
    String? timeOfDay,
  }) {
    Query query = _firestore.collection('schedules');

    if (date != null) {
      final startOfDay = DateTime(date.year, date.month, date.day);
      final endOfDay = DateTime(date.year, date.month, date.day, 23, 59, 59);
      query = query
          .where('schedule_date', isGreaterThanOrEqualTo: startOfDay)
          .where('schedule_date', isLessThanOrEqualTo: endOfDay);
    }

    if (timeOfDay != null) {
      query = query.where('time_of_day', isEqualTo: timeOfDay);
    }

    return query.snapshots().map(
      (snapshot) =>
          snapshot.docs.map((doc) => ScheduleModel.fromFirestore(doc)).toList(),
    );
  }

  Future<void> addSchedule(ScheduleModel schedule) async {
    await _firestore.collection('schedules').add(schedule.toFirestore());
  }

  Future<void> updateSchedule(String scheduleId, ScheduleModel schedule) async {
    await _firestore
        .collection('schedules')
        .doc(scheduleId)
        .update(schedule.toFirestore());
  }

  Future<void> deleteSchedule(String scheduleId) async {
    await _firestore.collection('schedules').doc(scheduleId).delete();
  }

  // BARU: Hapus semua schedules berdasarkan device_id
  Future<void> deleteSchedulesByDevice(String deviceId) async {
    final snapshot = await _firestore
        .collection('schedules')
        .where('device_id', isEqualTo: deviceId)
        .get();

    final batch = _firestore.batch();
    for (var doc in snapshot.docs) {
      batch.delete(doc.reference);
    }
    await batch.commit();
  }
}
