import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';

import '../../repositories/auth_repository.dart';
import '../../services/supabase_auth_service.dart'; // Dibutuhkan untuk DI di authRepositoryProvider
import 'auth_state.dart';

// ── Provider ────────────────────────────────────────────────────
/// Provider global untuk [AuthRepository].
final authRepositoryProvider = Provider<AuthRepository>(
  (ref) => AuthRepository(SupabaseAuthService()),
);

/// Provider utama untuk mengelola status autentikasi di seluruh aplikasi.
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>(
  (ref) => AuthNotifier(ref.read(authRepositoryProvider)),
);

// ── Notifier ────────────────────────────────────────────────────
/// Notifier yang mengelola logika bisnis autentikasi pengguna.
/// Berfungsi sebagai penghubung antara UI dan [AuthRepository], serta mengontrol pendaftaran OneSignal Push Notification.
class AuthNotifier extends StateNotifier<AuthState> {
  final AuthRepository _repo;

  AuthNotifier(this._repo) : super(const AuthIdle());

  /// Memeriksa status sesi login yang tersimpan di perangkat lokal.
  /// Dipanggil pertama kali saat aplikasi dibuka untuk fitur Auto-Login.
  Future<void> checkAuthStatus() async {
    state = const AuthLoading();
    try {
      // Mengambil sesi aktif dari repository
      final user = await _repo.checkSession();

      if (user != null) {
        // Jika sesi valid, login ke OneSignal menggunakan ID user untuk pengiriman notifikasi personal
        OneSignal.login(user.id);
        state = AuthSuccess(user);
      } else {
        state = const AuthIdle();
      }
    } catch (e) {
      state = const AuthIdle();
    }
  }

  /// Memproses login pengguna menggunakan email dan password.
  Future<void> login(String email, String password) async {
    state = const AuthLoading();
    try {
      final user = await _repo.login(email, password);
      // Daftarkan ke OneSignal saat login berhasil
      OneSignal.login(user.id);
      state = AuthSuccess(user);
    } catch (e) {
      state = AuthError(e.toString().replaceFirst('Exception: ', ''));
    }
  }

  /// Memproses registrasi akun baru (Nama, Email, Password).
  Future<void> register(
      String name, String email, String password) async {
    state = const AuthLoading();
    try {
      final user = await _repo.register(name, email, password);
      // Daftarkan ke OneSignal saat registrasi berhasil
      OneSignal.login(user.id);
      state = AuthSuccess(user);
    } catch (e) {
      state = AuthError(e.toString().replaceFirst('Exception: ', ''));
    }
  }

  /// Menghubungkan akun pengguna dengan perangkat IoT ESP32 berdasarkan [claimCode] dari alat.
  /// Setelah berhasil diklaim, state [AuthState] akan diperbarui dengan data `deviceId` yang baru.
  Future<void> claimDevice(String claimCode) async {
    final currentState = state;
    if (currentState is! AuthSuccess) return;

    state = const AuthLoading();
    try {
      final deviceId = await _repo.claimDevice(currentState.user.id, claimCode);
      // Update UserModel dengan deviceId baru secara immutable
      final updatedUser = currentState.user.copyWith(deviceId: deviceId);
      state = AuthSuccess(updatedUser);
    } catch (e) {
      // Revert ke state sebelumnya jika terjadi error klaim
      state = currentState;
      rethrow;
    }
  }

  /// Keluar dari sesi login pengguna.
  /// Menghapus kredensial dari Supabase, memutus sesi OneSignal, dan mereset state ke [AuthIdle].
  Future<void> logout() async {
    OneSignal.logout();
    await _repo.logout();
    state = const AuthIdle();
  }

  /// Mereset kondisi error saat ini kembali ke [AuthIdle].
  void resetError() {
    if (state is AuthError) state = const AuthIdle();
  }
}
