import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/foundation.dart';
import '../models/user_model.dart';
import '../core/api_config.dart';
import 'auth_service.dart';

/// Implementasi [AuthService] menggunakan layanan **Supabase Auth** untuk autentikasi user
/// dan **SharedPreferences** untuk menyimpan cache lokal data `device_id` IoT.
class SupabaseAuthService implements AuthService {
  final supabase.SupabaseClient _client = supabase.Supabase.instance.client;
  final Dio _dio = Dio();

  @override
  Future<UserModel> login(String email, String password) async {
    try {
      // 1. Melakukan sign in ke Supabase Auth
      final response = await _client.auth.signInWithPassword(
        email: email,
        password: password,
      );
      
      final user = response.user;
      if (user == null) {
        throw Exception('Login gagal: User tidak ditemukan');
      }

      // 2. Mengambil informasi device_id yang terhubung ke pengguna dari database backend
      String? deviceId;
      try {
        final deviceRes = await _dio.get('${ApiConfig.baseUrl}/device/my-device/${user.id}');
        if (deviceRes.statusCode == 200) {
          deviceId = deviceRes.data['device_id'];
        }
      } catch (e) {
        debugPrint('Gagal mengambil info device: $e');
        // Tidak melempar error agar login tetap sukses meskipun user belum menghubungkan device
      }

      // 3. Menyimpan device_id ke cache lokal (SharedPreferences) agar auto-login selanjutnya lebih cepat dan offline-safe
      if (deviceId != null) {
        final prefs = await SharedPreferences.getInstance();
        await prefs.setString('cached_device_id', deviceId);
      }

      return UserModel(
        id: user.id,
        name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User',
        email: user.email ?? email,
        token: response.session?.accessToken ?? '',
        deviceId: deviceId,
      );
    } on supabase.AuthException catch (e) {
      // Pemetaan pesan error dari Supabase ke bahasa Indonesia yang ramah pengguna
      if (e.message.contains('Invalid login credentials')) {
        throw Exception('Email atau password salah.');
      } else if (e.message.contains('Email not confirmed')) {
        throw Exception('Email belum diverifikasi.');
      }
      throw Exception(e.message);
    } catch (e) {
      throw Exception('Terjadi kesalahan koneksi atau server.');
    }
  }

  @override
  Future<UserModel> register(String name, String email, String password) async {
    try {
      // Melakukan pendaftaran akun ke Supabase Auth beserta meta data nama lengkap
      final response = await _client.auth.signUp(
        email: email,
        password: password,
        data: {'name': name},
      );

      final user = response.user;
      if (user == null) {
        throw Exception('Registrasi gagal');
      }

      return UserModel(
        id: user.id,
        name: name,
        email: email,
        token: response.session?.accessToken ?? '',
        deviceId: null,
      );
    } on supabase.AuthException catch (e) {
      if (e.message.contains('already registered')) {
        throw Exception('Email sudah terdaftar.');
      } else if (e.message.contains('weak')) {
        throw Exception('Password terlalu lemah.');
      }
      throw Exception(e.message);
    } catch (e) {
      throw Exception('Terjadi kesalahan koneksi atau server.');
    }
  }

  @override
  Future<String> claimDevice(String userId, String claimCode) async {
    try {
      // Mengirim request klaim alat ke REST API backend
      final claimRes = await _dio.post('${ApiConfig.baseUrl}/device/claim', data: {
        'claim_code': claimCode.trim(),
        'user_id': userId,
      });

      if (claimRes.statusCode == 200) {
        final deviceId = claimRes.data['device']['device_id'] as String;
        // Menyimpan ID perangkat yang berhasil diklaim ke SharedPreferences
        final prefs = await SharedPreferences.getInstance();
        await prefs.setString('cached_device_id', deviceId);
        return deviceId;
      } else {
        throw Exception('Gagal klaim perangkat: ${claimRes.statusCode}');
      }
    } catch (e) {
      String errorMsg = 'Gagal klaim perangkat.';
      if (e is DioException && e.response?.data != null) {
        errorMsg = e.response?.data['message'] ?? errorMsg;
      }
      throw Exception(errorMsg);
    }
  }

  @override
  Future<void> logout() async {
    // 1. Membersihkan sesi Supabase Auth di server
    await _client.auth.signOut();
    
    // 2. Menghapus cache lokal device_id agar bersih saat login pengguna lain
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('cached_device_id');
  }

  /// Memulihkan sesi login yang tersimpan di internal storage untuk Auto-Login.
  /// Mengambil data user dari sesi aktif Supabase, dan device_id dari SharedPreferences.
  @override
  Future<UserModel?> checkSession() async {
    final session = _client.auth.currentSession;
    if (session != null) {
      final user = session.user;
      
      // Mengambil device_id dari cache lokal (cepat & aman saat offline)
      String? deviceId;
      try {
        final prefs = await SharedPreferences.getInstance();
        deviceId = prefs.getString('cached_device_id');
      } catch (e) {
        debugPrint('Gagal membaca cache device_id: $e');
      }

      return UserModel(
        id: user.id,
        name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User',
        email: user.email ?? '',
        token: session.accessToken,
        deviceId: deviceId,
      );
    }
    return null;
  }
}
