import 'dart:convert';
import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/core/database/models/enums.dart';

part 'loyalty_point_entry_model.g.dart';

@HiveType(typeId: HiveTypeIds.loyaltyPointEntryModel)
class LoyaltyPointEntryModel extends HiveObject {
  LoyaltyPointEntryModel({
    required this.entryId,
    required this.userId,
    required this.points,
    required this.entryType,
    required this.source,
    required this.description,
    this.referenceId,
    this.referenceType,
    this.complaint,
    required this.complaintStatus,
    required this.balanceAfter,
    this.expiryDate,
    required this.timestamp,
    this.erpnextEntryId,
  });

  @HiveField(0)
  final String entryId;
  @HiveField(1)
  final String userId;
  @HiveField(2)
  final int points;
  @HiveField(3)
  final EntryType entryType;
  @HiveField(4)
  final EntrySource source;
  @HiveField(5)
  final String description;
  @HiveField(6)
  final String? referenceId;
  @HiveField(7)
  final String? referenceType;
  @HiveField(8)
  final String? complaint;
  @HiveField(9)
  final ComplaintStatus complaintStatus;
  @HiveField(10)
  final int balanceAfter;
  @HiveField(11)
  final DateTime? expiryDate;
  @HiveField(12)
  final DateTime timestamp;
  @HiveField(13)
  final String? erpnextEntryId;

  factory LoyaltyPointEntryModel.fromJson(
    Map<String, dynamic> json,
  ) => LoyaltyPointEntryModel(
    entryId: json['entry_id'] as String,
    userId: json['user_id'] as String,
    points: json['points'] as int,
    entryType: EntryType.values.firstWhere((e) => e.name == json['entry_type']),
    source: EntrySource.values.firstWhere((e) => e.name == json['source']),
    description: json['description'] as String,
    referenceId: json['reference_id'] as String?,
    referenceType: json['reference_type'] as String?,
    complaint: json['complaint'] != null ? jsonEncode(json['complaint']) : null,
    complaintStatus: ComplaintStatus.values.firstWhere(
      (e) => e.name == (json['complaint_status'] ?? 'none'),
    ),
    balanceAfter: json['balance_after'] as int,
    expiryDate: json['expiry_date'] != null
        ? DateTime.parse(json['expiry_date']?.toString() ?? '')
        : null,
    timestamp: DateTime.parse(json['timestamp']?.toString() ?? ''),
    erpnextEntryId: json['erpnext_entry_id'] as String?,
  );

  Map<String, dynamic> toJson() => {
    'entry_id': entryId,
    'user_id': userId,
    'points': points,
    'entry_type': entryType.name,
    'source': source.name,
    'description': description,
    'reference_id': referenceId,
    'reference_type': referenceType,
    'complaint': complaint != null ? jsonDecode(complaint!) : null,
    'complaint_status': complaintStatus.name,
    'balance_after': balanceAfter,
    'expiry_date': expiryDate?.toIso8601String(),
    'timestamp': timestamp.toIso8601String(),
    'erpnext_entry_id': erpnextEntryId,
  };

  Map<String, dynamic>? get complaintMap {
    if (complaint == null) return null;
    try {
      return jsonDecode(complaint!) as Map<String, dynamic>;
    } catch (e) {
      return null;
    }
  }

  bool get isExpired =>
      expiryDate != null && DateTime.now().isAfter(expiryDate!);
  bool get hasComplaint => complaintStatus != ComplaintStatus.none;
}
