import 'dart:convert';
import 'package:hive_ce/hive.dart';
import '../models/product_model.dart';

/// Abstract interface for products local data source
abstract class ProductsLocalDataSource {
  /// Get cached products for a specific warehouse and operation type
  ///
  /// [warehouseId] - The ID of the warehouse
  /// [type] - The operation type ('import' or 'export')
  ///
  /// Returns List<ProductModel> from cache or empty list if not found
  Future<List<ProductModel>> getCachedProducts(int warehouseId, String type);

  /// Cache products for a specific warehouse and operation type
  ///
  /// [warehouseId] - The ID of the warehouse
  /// [type] - The operation type ('import' or 'export')
  /// [products] - List of products to cache
  Future<void> cacheProducts(
    int warehouseId,
    String type,
    List<ProductModel> products,
  );

  /// Clear all cached products
  Future<void> clearCache();

  /// Clear cached products for a specific warehouse and operation type
  Future<void> clearCachedProducts(int warehouseId, String type);
}

/// Implementation of ProductsLocalDataSource using Hive
class ProductsLocalDataSourceImpl implements ProductsLocalDataSource {
  static const String _boxName = 'products_cache';
  Box<String>? _box;

  /// Initialize the Hive box
  Future<void> init() async {
    if (_box == null || !_box!.isOpen) {
      _box = await Hive.openBox<String>(_boxName);
    }
  }

  /// Generate cache key for warehouse and operation type
  String _getCacheKey(int warehouseId, String type) {
    return 'products_${warehouseId}_$type';
  }

  @override
  Future<List<ProductModel>> getCachedProducts(
    int warehouseId,
    String type,
  ) async {
    await init();

    final key = _getCacheKey(warehouseId, type);
    final cachedData = _box?.get(key);

    if (cachedData == null) {
      return [];
    }

    try {
      // Decode JSON string to list
      final jsonList = jsonDecode(cachedData) as List;

      // Convert JSON list to ProductModel list
      return jsonList
          .map((json) => ProductModel.fromJson(json as Map<String, dynamic>))
          .toList();
    } catch (e) {
      // If parsing fails, return empty list
      return [];
    }
  }

  @override
  Future<void> cacheProducts(
    int warehouseId,
    String type,
    List<ProductModel> products,
  ) async {
    await init();

    final key = _getCacheKey(warehouseId, type);

    // Convert products to JSON list
    final jsonList = products.map((product) => product.toJson()).toList();

    // Encode to JSON string and save
    final jsonString = jsonEncode(jsonList);
    await _box?.put(key, jsonString);
  }

  @override
  Future<void> clearCache() async {
    await init();
    await _box?.clear();
  }

  @override
  Future<void> clearCachedProducts(int warehouseId, String type) async {
    await init();

    final key = _getCacheKey(warehouseId, type);
    await _box?.delete(key);
  }
}
