import 'package:dio/dio.dart';
import 'package:worker/core/constants/api_constants.dart';
import 'package:worker/core/errors/exceptions.dart';
import 'package:worker/features/products/data/models/product_model.dart';

/// Favorites Remote DataSource
///
/// Handles all API operations for favorites/wishlist using Frappe ERPNext backend.
/// Follows the API spec from docs/favorite.sh
///
/// Note: The API returns Product objects directly, not separate favorite entities.
class FavoritesRemoteDataSource {
  FavoritesRemoteDataSource(this._dio);

  final Dio _dio;

  /// Get all favorites/wishlist items for the current user
  ///
  /// API: POST /api/method/building_material.building_material.api.item_wishlist.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  ///
  /// Response format (from docs/favorite.sh):
  /// ```json
  /// {
  ///   "message": [
  ///     {
  ///       "name": "GIB20 G04",
  ///       "item_code": "GIB20 G04",
  ///       "item_name": "Gibellina GIB20 G04",
  ///       "item_group_name": "OUTDOOR [20mm]",
  ///       "custom_link_360": "https://...",
  ///       "thumbnail": "https://...",
  ///       "price": 0,
  ///       "currency": "",
  ///       "conversion_of_sm": 5.5556
  ///     }
  ///   ]
  /// }
  /// ```
  ///
  /// Returns list of Product objects that are favorited
  Future<List<ProductModel>> getFavorites({
    int limitStart = 0,
    int limitPageLength = 0, // 0 means get all
  }) async {
    try {
      final response = await _dio.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.getFavorites}',
        data: {
          'limit_start': limitStart,
          'limit_page_length': limitPageLength,
        },
      );

      if (response.data == null) {
        throw const ServerException('Response data is null');
      }

      // Parse response according to Frappe format
      final data = response.data!;
      final messageList = data['message'] as List<dynamic>?;

      if (messageList == null || messageList.isEmpty) {
        _debugPrint('No favorites found');
        return [];
      }

      final products = <ProductModel>[];

      // Convert API response - each item is a product object from wishlist
      for (final item in messageList) {
        try {
          final itemMap = item as Map<String, dynamic>;
          final productModel = ProductModel.fromWishlistApi(itemMap);
          products.add(productModel);
        } catch (e) {
          _debugPrint('Error parsing product: $e');
          // Continue with other products even if one fails
        }
      }

      _debugPrint('Fetched ${products.length} favorite products');
      return products;
    } on DioException catch (e) {
      _handleDioException(e);
    } catch (e) {
      _debugPrint('Error getting favorites: $e');
      throw ServerException('Failed to get favorites: $e');
    }
  }

  /// Add item to wishlist
  ///
  /// API: POST /api/method/building_material.building_material.api.item_wishlist.add_to_wishlist
  /// Body: { "item_id": "GIB20 G04" }
  ///
  /// Returns true if successful
  Future<bool> addToFavorites(String itemId) async {
    try {
      final response = await _dio.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.addToFavorites}',
        data: {
          'item_id': itemId,
        },
      );

      _debugPrint('Added to favorites: $itemId');
      return response.statusCode == 200;
    } on DioException catch (e) {
      _handleDioException(e);
    } catch (e) {
      _debugPrint('Error adding to favorites: $e');
      throw ServerException('Failed to add to favorites: $e');
    }
  }

  /// Remove item from wishlist
  ///
  /// API: POST /api/method/building_material.building_material.api.item_wishlist.remove_from_wishlist
  /// Body: { "item_id": "GIB20 G04" }
  ///
  /// Returns true if successful
  Future<bool> removeFromFavorites(String itemId) async {
    try {
      final response = await _dio.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.removeFromFavorites}',
        data: {
          'item_id': itemId,
        },
      );

      _debugPrint('Removed from favorites: $itemId');
      return response.statusCode == 200;
    } on DioException catch (e) {
      _handleDioException(e);
    } catch (e) {
      _debugPrint('Error removing from favorites: $e');
      throw ServerException('Failed to remove from favorites: $e');
    }
  }

  // =========================================================================
  // ERROR HANDLING
  // =========================================================================

  /// Handle Dio exceptions and convert to custom exceptions
  Never _handleDioException(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        throw const NetworkException('Request timeout. Please check your connection.');

      case DioExceptionType.connectionError:
        throw const NetworkException('No internet connection.');

      case DioExceptionType.badResponse:
        final statusCode = e.response?.statusCode;
        final message = e.response?.data?['message'] as String? ??
            e.response?.data?['error'] as String? ??
            'Server error';

        if (statusCode == 401) {
          throw const UnauthorizedException('Unauthorized. Please login again.');
        } else if (statusCode == 403) {
          throw const UnauthorizedException('Access forbidden.');
        } else if (statusCode == 404) {
          throw const ServerException('Resource not found.');
        } else if (statusCode != null && statusCode >= 500) {
          throw ServerException('Server error: $message');
        } else {
          throw ServerException(message);
        }

      case DioExceptionType.cancel:
        throw const NetworkException('Request was cancelled');

      case DioExceptionType.unknown:
      case DioExceptionType.badCertificate:
        throw NetworkException('Network error: ${e.message}');
    }
  }
}

// ============================================================================
// DEBUG UTILITIES
// ============================================================================

/// Debug print helper
void _debugPrint(String message) {
  // ignore: avoid_print
  print('[FavoritesRemoteDataSource] $message');
}
