// lib/core/service/student_service.dart

import 'dart:convert';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:googleapis_auth/auth_io.dart' as auth;
import 'package:http/http.dart' as http;
import 'package:smpn1_lengkong/core/models/attendance_log_model.dart';
import 'package:smpn1_lengkong/core/models/student_model.dart';
import 'package:smpn1_lengkong/core/models/violation_history_model.dart';
import 'package:url_launcher/url_launcher.dart';

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

  Future<StudentModel> getCurrentStudentData() async {
    try {
      final user = _auth.currentUser;
      if (user == null) {
        throw Exception("Sesi berakhir, silakan login kembali.");
      }

      // MODIFIKASI: Menambahkan GetOptions agar mengambil data terbaru dari server
      // Ini memastikan informasi pribadi yang baru diedit langsung sinkron
      DocumentSnapshot studentDoc = await _firestore
          .collection('siswa')
          .doc(user.uid)
          .get(const GetOptions(source: Source.serverAndCache));

      if (!studentDoc.exists) throw Exception("Data siswa tidak ditemukan.");

      // Bagian pengambilan data pelanggaran tetap sama
      QuerySnapshot violationSnapshot =
          await _firestore
              .collection('violations')
              .where('student_id', isEqualTo: user.uid)
              .get();

      List<ViolationHistory> realViolations =
          violationSnapshot.docs.map((v) {
            return ViolationHistory.fromFirestore(
              v.data() as Map<String, dynamic>,
            );
          }).toList();

      // Ambil data absensi real
      List<AttendanceLog> realAttendance = await getAttendanceData(user.uid);

      return StudentModel.fromFirestore(
        studentDoc.data() as Map<String, dynamic>,
        studentDoc.id,
        violations: realViolations,
        attendance: realAttendance,
      );
    } catch (e) {
      rethrow;
    }
  }

  Future<List<AttendanceLog>> getAttendanceData(String studentId) async {
    List<AttendanceLog> logs = [];
    try {
      // Ambil data dari koleksi 'absensi'
      QuerySnapshot absensiSnapshot =
          await _firestore.collection('absensi').get();

      for (var doc in absensiSnapshot.docs) {
        Map<String, dynamic> docData = doc.data() as Map<String, dynamic>;

        // Cek apakah data untuk UID siswa ini ada di dokumen tersebut
        if (docData['data'] != null && docData['data'][studentId] != null) {
          var studentRecord = docData['data'][studentId];
          var metadata = docData['metadata'];

          // Ambil tanggal dari metadata (format YYYY-MM-DD)
          String? rawDate = metadata != null ? metadata['tanggal'] : null;

          if (rawDate != null) {
            logs.add(
              AttendanceLog(
                date: DateTime.parse(rawDate),
                status: studentRecord['status'] ?? 'Hadir',
                description: studentRecord['mapel'] ?? '-',
                className: studentRecord['kelas'] ?? '-',
              ),
            );
          }
        }
      }
      // Urutkan dari yang terbaru
      logs.sort((a, b) => b.date.compareTo(a.date));
      return logs;
    } catch (e) {
      debugPrint("Error detail fetch absensi: $e");
      return [];
    }
  }

  Future<List<Map<String, dynamic>>> getBimbinganHistory(
    String studentId,
    String className,
  ) async {
    try {
      final snapshot =
          await _firestore
              .collection('Bimbingan')
              .where('student_id', isEqualTo: studentId)
              .where(
                'kelas',
                isEqualTo: className,
              ) // Filter berdasarkan kelas yang sedang dilihat
              .orderBy('createdAt', descending: true)
              .get();

      return snapshot.docs.map((doc) => {'id': doc.id, ...doc.data()}).toList();
    } catch (e) {
      debugPrint("Error detail fetch bimbingan: $e");
      return [];
    }
  }

  // Di dalam class StudentService
  Future<List<Map<String, dynamic>>> getNotifications(
    String userId,
    String className,
  ) async {
    final snapshot =
        await _firestore
            .collection('notifikasi')
            .where('id_user', isEqualTo: userId)
            .where('kelas', isEqualTo: className) // TAMBAHKAN FILTER INI
            .get();
    return snapshot.docs.map((doc) => {'id': doc.id, ...doc.data()}).toList();
  }

  Future<void> markNotificationAsRead(String notificationId) async {
    await _firestore.collection('notifikasi').doc(notificationId).update({
      'status': 'read',
    });
  }

  Future<void> markAllAsRead(String userId, String className) async {
    try {
      // Ambil semua notifikasi unread milik user di kelas ini
      final querySnapshot =
          await _firestore
              .collection('notifikasi')
              .where('id_user', isEqualTo: userId)
              .where('kelas', isEqualTo: className)
              .where('status', isEqualTo: 'unread')
              .get();

      if (querySnapshot.docs.isEmpty) return;

      // Gunakan WriteBatch untuk efisiensi update massal
      WriteBatch batch = _firestore.batch();
      for (var doc in querySnapshot.docs) {
        batch.update(doc.reference, {'status': 'read'});
      }

      await batch.commit();
    } catch (e) {
      debugPrint("Error mark all as read: $e");
    }
  }

  Future<String> _getAccessToken() async {
    try {
      // Pastikan nama file ini sesuai dengan yang ada di folder assets dan pubspec.yaml
      final serviceAccountJson = await rootBundle.loadString(
        'assets/service.json',
      );
      final data = json.decode(serviceAccountJson);

      final accountCredentials = auth.ServiceAccountCredentials.fromJson(data);
      final scopes = ['https://www.googleapis.com/auth/firebase.messaging'];

      final client = await auth.clientViaServiceAccount(
        accountCredentials,
        scopes,
      );
      return client.credentials.accessToken.data;
    } catch (e) {
      debugPrint("Gagal mendapatkan Access Token: $e");
      rethrow;
    }
  }

Future<void> _sendPushNotification(
  String token,
  String title,
  String body,
) async {
  try {
    final String accessToken = await _getAccessToken();
    const String projectId = 'smpn1lengkong-b7621';
    final String url = 'https://fcm.googleapis.com/v1/projects/$projectId/messages:send';

    final response = await http.post(
      Uri.parse(url),
      headers: <String, String>{
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $accessToken',
      },
      body: jsonEncode({
        'message': {
          'token': token,
          'notification': {'title': title, 'body': body},
          'android': {
            'priority': 'high', // Memastikan prioritas tinggi
            'notification': {
              'channel_id': 'high_importance_channel', // Harus sama dengan di FcmService
              'sound': 'default',
              'click_action': 'FLUTTER_NOTIFICATION_CLICK', // Penting untuk perangkat fisik
              'notification_priority': 'PRIORITY_MAX', // Tambahan untuk Android lawas/fisik
            },
          },
          'data': {
            'type': 'info',
            'click_action': 'FLUTTER_NOTIFICATION_CLICK',
          },
        },
      }),
    );

    // Tambahkan log untuk debugging di perangkat fisik
    if (response.statusCode != 200) {
      debugPrint("FCM Error: ${response.statusCode} - ${response.body}");
    }
  } catch (e) {
    debugPrint("Error FCM V1: $e");
  }
}

  // 3. Fungsi Update Data & Trigger Notifikasi
  Future<void> updateStudentPersonalData({
    required StudentModel student,
    required String fatherName,
    required String motherName,
    required String job,
    required String address,
    required String phoneNumber,
  }) async {
    try {
      // Update Profil Siswa
      await _firestore.collection('siswa').doc(student.id).update({
        'nama_ayah': fatherName,
        'nama_ibu': motherName,
        'pekerjaan_ortu': job,
        'alamat': address,
        'no_hp': phoneNumber,
        'updated_at': FieldValue.serverTimestamp(),
      });

      // Ambil Token FCM
      DocumentSnapshot userDoc =
          await _firestore.collection('siswa').doc(student.id).get();
      String? fcmToken = userDoc.get('fcm_token');

      final String currentTime = DateTime.now().toString().substring(0, 19);
      final String title = "📝 Pembaruan Informasi Pribadi";
      final String body =
          "Yth. Bapak/Ibu Wali, Informasi pribadi untuk siswa atas nama ${student.name} telah berhasil diperbarui. Terima kasih.";

      // Tambah Dokumen ke Koleksi Notifikasi
      await _firestore.collection('notifikasi').add({
        'id_user': student.id,
        'angkatan': student.angkatan,
        'body': body,
        'tanggal': currentTime,
        'fcm_token': fcmToken ?? "",
        'kelas': student.className,
        'nama_siswa': student.name,
        'siswa_id': student.id,
        'status': 'unread',
        'title': title,
        'type': 'info',
      });

      // Kirim Notifikasi ke Device
      if (fcmToken != null && fcmToken.isNotEmpty) {
        await _sendPushNotification(fcmToken, title, body);
      }
    } catch (e) {
      debugPrint("Error update data: $e");
      throw Exception("Gagal menyimpan perubahan.");
    }
  }

  // Fungsi untuk mengambil link WA dari koleksi administrasi
  Future<String?> getContactLink() async {
    try {
      // Memastikan query sesuai dengan aturan read di Firebase
      final snapshot =
          await _firestore.collection('administrasi').limit(1).get();

      if (snapshot.docs.isNotEmpty) {
        return snapshot.docs.first.data()['contact'];
      }
      return null;
    } catch (e) {
      // Jika masih error permission, akan tercetak di sini
      debugPrint("Error fetch contact: $e");
      return null;
    }
  }

  // lib/core/service/student_service.dart
  Future<void> launchWhatsApp(String url) async {
    try {
      final Uri uri = Uri.parse(url);

      // Gunakan LaunchMode.externalApplication agar Android
      // langsung mencari aplikasi WA atau Browser di luar app kita
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri, mode: LaunchMode.externalApplication);
      } else {
        throw 'WhatsApp tidak terinstal atau tautan tidak valid';
      }
    } catch (e) {
      debugPrint("Error launching URL: $e");
      rethrow;
    }
  }

  Future<void> sendBimbinganNotification({
  required String studentId,
  required String studentName,
  required String className,
  required String category,
}) async {
  try {
    // 1. Ambil Token FCM terbaru dari database
    DocumentSnapshot userDoc = await _firestore.collection('siswa').doc(studentId).get();
    String? fcmToken = userDoc.get('fcm_token');

    final String currentTime = DateTime.now().toString().substring(0, 19);
    final String title = "🗓️ Permohonan Kunjungan Dikirim";
    final String body = "Permohonan kunjungan untuk $studentName (Kelas $className) telah berhasil diajukan ke sekolah. Mohon tunggu konfirmasi jadwal.";

    // 2. Simpan ke koleksi 'notifikasi' agar tampil di NotificationScreen
    await _firestore.collection('notifikasi').add({
      'id_user': studentId,
      'body': body,
      'tanggal': currentTime,
      'fcm_token': fcmToken ?? "",
      'kelas': className,
      'nama_siswa': studentName,
      'siswa_id': studentId,
      'status': 'unread',
      'title': title,
      'type': 'info',
    });

    // 3. Kirim Push Notification ke perangkat
    if (fcmToken != null && fcmToken.isNotEmpty) {
      await _sendPushNotification(fcmToken, title, body);
    }
  } catch (e) {
    debugPrint("Gagal mengirim notifikasi bimbingan: $e");
  }
}
}
