/// Data Source: Points History Local Data Source
///
/// Handles local storage operations for loyalty points history using Hive.
library;

import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/core/database/models/enums.dart';
import 'package:worker/features/loyalty/data/models/loyalty_point_entry_model.dart';

/// Points History Local Data Source
///
/// Provides methods to interact with locally stored points history data.
class PointsHistoryLocalDataSource {
  Box? _entriesBox;

  /// Get Hive box for points entries
  Future<Box> get entriesBox async {
    if (_entriesBox != null) return _entriesBox!;

    // Use the box already opened by HiveService
    if (Hive.isBoxOpen(HiveBoxNames.loyaltyBox)) {
      _entriesBox = Hive.box(HiveBoxNames.loyaltyBox);
    } else {
      _entriesBox = await Hive.openBox(HiveBoxNames.loyaltyBox);
    }

    return _entriesBox!;
  }

  /// Get all points entries
  Future<List<LoyaltyPointEntryModel>> getAllEntries() async {
    final box = await entriesBox;
    final entries = box.values.whereType<LoyaltyPointEntryModel>().toList();
    entries.sort((a, b) => b.timestamp.compareTo(a.timestamp)); // Newest first
    return entries;
  }

  /// Get entry by ID
  Future<LoyaltyPointEntryModel?> getEntryById(String entryId) async {
    final box = await entriesBox;
    try {
      return box.values.whereType<LoyaltyPointEntryModel>().firstWhere(
        (entry) => entry.entryId == entryId,
      );
    } catch (e) {
      throw Exception('Entry not found');
    }
  }

  /// Save entry
  Future<void> saveEntry(LoyaltyPointEntryModel entry) async {
    final box = await entriesBox;
    await box.put(entry.entryId, entry);
  }

  /// Save multiple entries
  Future<void> saveEntries(List<LoyaltyPointEntryModel> entries) async {
    final box = await entriesBox;
    final Map<String, LoyaltyPointEntryModel> entriesMap = {
      for (var entry in entries) entry.entryId: entry,
    };
    await box.putAll(entriesMap);
  }

  /// Delete entry
  Future<void> deleteEntry(String entryId) async {
    final box = await entriesBox;
    await box.delete(entryId);
  }

  /// Clear all entries
  Future<void> clearEntries() async {
    final box = await entriesBox;
    await box.clear();
  }

  /// Seed mock data for development
  Future<void> seedMockEntries() async {
    final now = DateTime.now();

    final mockEntries = [
      LoyaltyPointEntryModel(
        entryId: 'entry_001',
        userId: 'user_001',
        points: 3,
        entryType: EntryType.earn,
        source: EntrySource.purchase,
        description: 'Giao dịch mua hàng 00083',
        referenceId: 'order_00083',
        referenceType: 'order',
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: now.add(const Duration(days: 365)),
        timestamp: DateTime(2025, 9, 28, 17, 23, 18),
      ),
      LoyaltyPointEntryModel(
        entryId: 'entry_002',
        userId: 'user_001',
        points: 0,
        entryType: EntryType.earn,
        source: EntrySource.purchase,
        description: 'Giao dịch mua hàng 00081',
        referenceId: 'order_00081',
        referenceType: 'order',
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: now.add(const Duration(days: 365)),
        timestamp: DateTime(2025, 9, 27, 17, 23, 18),
      ),
      LoyaltyPointEntryModel(
        entryId: 'entry_003',
        userId: 'user_001',
        points: -5,
        entryType: EntryType.expiry,
        source: EntrySource.promotion,
        description: 'Điểm thưởng hết hạn',
        referenceId: null,
        referenceType: null,
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: null,
        timestamp: DateTime(2025, 9, 20, 17, 23, 18),
      ),
      LoyaltyPointEntryModel(
        entryId: 'entry_004',
        userId: 'user_001',
        points: -500,
        entryType: EntryType.redeem,
        source: EntrySource.giftRedemption,
        description: 'Đổi Voucher HSG',
        referenceId: 'gift_001',
        referenceType: 'gift',
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: null,
        timestamp: DateTime(2025, 9, 19, 17, 23, 18),
      ),
      LoyaltyPointEntryModel(
        entryId: 'entry_005',
        userId: 'user_001',
        points: 5,
        entryType: EntryType.earn,
        source: EntrySource.referral,
        description: 'Giới thiệu người dùng',
        referenceId: null,
        referenceType: null,
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: now.add(const Duration(days: 365)),
        timestamp: DateTime(2025, 9, 10, 17, 23, 18),
      ),
      LoyaltyPointEntryModel(
        entryId: 'entry_006',
        userId: 'user_001',
        points: -200,
        entryType: EntryType.redeem,
        source: EntrySource.giftRedemption,
        description: 'Đổi quà',
        referenceId: 'gift_002',
        referenceType: 'gift',
        complaint: null,
        complaintStatus: ComplaintStatus.none,
        balanceAfter: 604,
        expiryDate: null,
        timestamp: DateTime(2025, 9, 5, 17, 23, 18),
      ),
    ];

    await saveEntries(mockEntries);
  }

  /// Get transaction amount from description (for purchase entries)
  int? getTransactionAmount(String description) {
    if (description.contains('Giao dịch mua hàng 00083')) {
      return 100000000; // 100M VND
    } else if (description.contains('Giao dịch mua hàng 00081')) {
      return 200000000; // 200M VND
    }
    return null;
  }
}
