import 'package:dio/dio.dart';
import 'package:real_estate_mobile/core/network/api_client.dart';
import 'package:real_estate_mobile/core/network/api_exceptions.dart';
import 'package:real_estate_mobile/features/notifications/data/models/notification_model.dart';

class NotificationRepository {
  final Dio _dio = ApiClient.instance.dio;

  /// Fetch notifications with optional filter and pagination.
  /// GET /notifications?filter=all|unread&page=1&limit=20
  Future<NotificationsResponse> getNotifications({
    String filter = 'all',
    int page = 1,
    int limit = 20,
  }) async {
    try {
      final response = await _dio.get('/notifications', queryParameters: {
        'filter': filter,
        'page': page,
        'limit': limit,
      });
      final data = response.data['data'] as Map<String, dynamic>;
      return NotificationsResponse.fromJson(data);
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to fetch notifications',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Get unread notification count.
  /// GET /notifications/unread-count
  Future<int> getUnreadCount() async {
    try {
      final response = await _dio.get('/notifications/unread-count');
      final data = response.data['data'] as Map<String, dynamic>;
      return data['unreadCount'] as int? ?? 0;
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to fetch unread count',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Mark a single notification as read.
  /// PATCH /notifications/:id/read
  Future<void> markAsRead(String notificationId) async {
    try {
      await _dio.patch('/notifications/$notificationId/read');
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to mark notification as read',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Mark all notifications as read.
  /// PATCH /notifications/read-all
  Future<void> markAllAsRead() async {
    try {
      await _dio.patch('/notifications/read-all');
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to mark all as read',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Register FCM token with backend.
  /// POST /notifications/fcm-token
  Future<void> registerFcmToken(String token, String device) async {
    try {
      await _dio.post('/notifications/fcm-token', data: {
        'token': token,
        'device': device,
      });
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to register FCM token',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Remove FCM token from backend.
  /// DELETE /notifications/fcm-token
  Future<void> removeFcmToken(String token) async {
    try {
      await _dio.delete('/notifications/fcm-token', data: {
        'token': token,
      });
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to remove FCM token',
        statusCode: e.response?.statusCode,
      );
    }
  }
}

class NotificationsResponse {
  final List<AppNotification> notifications;
  final int unreadCount;
  final int totalPages;
  final int currentPage;

  const NotificationsResponse({
    required this.notifications,
    required this.unreadCount,
    required this.totalPages,
    required this.currentPage,
  });

  factory NotificationsResponse.fromJson(Map<String, dynamic> json) {
    final list = (json['notifications'] as List<dynamic>?)
            ?.map((e) => AppNotification.fromJson(e as Map<String, dynamic>))
            .toList() ??
        [];
    return NotificationsResponse(
      notifications: list,
      unreadCount: json['unreadCount'] as int? ?? 0,
      totalPages: json['totalPages'] as int? ?? 1,
      currentPage: json['currentPage'] as int? ?? 1,
    );
  }
}
