/// Data Model: Member Card
///
/// Data Transfer Object for member card information.
/// This model handles serialization/deserialization for:
/// - JSON (API responses)
/// - Hive (local database)
///
/// Extends the domain entity and adds data layer functionality.
library;

import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/features/home/domain/entities/member_card.dart';

part 'member_card_model.g.dart';

/// Member Card Model
///
/// Used for:
/// - API JSON serialization/deserialization
/// - Hive local database storage
/// - Converting to/from domain entity
///
/// Hive Type ID: 25 (from HiveTypeIds.memberCardModel)
@HiveType(typeId: HiveTypeIds.memberCardModel)
class MemberCardModel extends HiveObject {
  /// Member ID
  @HiveField(0)
  final String memberId;

  /// Member name
  @HiveField(1)
  final String name;

  /// Member type (stored as string for serialization)
  @HiveField(2)
  final String memberType;

  /// Membership tier (stored as string for serialization)
  @HiveField(3)
  final String tier;

  /// Current points
  @HiveField(4)
  final int points;

  /// Card expiration date (stored as ISO8601 string)
  @HiveField(5)
  final String validUntil;

  /// QR code data
  @HiveField(6)
  final String qrData;

  MemberCardModel({
    required this.memberId,
    required this.name,
    required this.memberType,
    required this.tier,
    required this.points,
    required this.validUntil,
    required this.qrData,
  });

  /// From JSON constructor
  factory MemberCardModel.fromJson(Map<String, dynamic> json) {
    return MemberCardModel(
      memberId: json['memberId'] as String,
      name: json['name'] as String,
      memberType: json['memberType'] as String,
      tier: json['tier'] as String,
      points: json['points'] as int,
      validUntil: json['validUntil'] as String,
      qrData: json['qrData'] as String,
    );
  }

  /// To JSON method
  Map<String, dynamic> toJson() {
    return {
      'memberId': memberId,
      'name': name,
      'memberType': memberType,
      'tier': tier,
      'points': points,
      'validUntil': validUntil,
      'qrData': qrData,
    };
  }

  /// Convert to domain entity
  MemberCard toEntity() {
    return MemberCard(
      memberId: memberId,
      name: name,
      memberType: _parseMemberType(memberType),
      tier: _parseMemberTier(tier),
      points: points,
      validUntil: DateTime.parse(validUntil),
      qrData: qrData,
    );
  }

  /// Create from domain entity
  factory MemberCardModel.fromEntity(MemberCard entity) {
    return MemberCardModel(
      memberId: entity.memberId,
      name: entity.name,
      memberType: entity.memberType.name,
      tier: entity.tier.name,
      points: entity.points,
      validUntil: entity.validUntil.toIso8601String(),
      qrData: entity.qrData,
    );
  }

  /// Parse member type from string
  static MemberType _parseMemberType(String type) {
    return MemberType.values.firstWhere(
      (e) => e.name.toLowerCase() == type.toLowerCase(),
      orElse: () => MemberType.contractor, // Default fallback
    );
  }

  /// Parse member tier from string
  static MemberTier _parseMemberTier(String tier) {
    return MemberTier.values.firstWhere(
      (e) => e.name.toLowerCase() == tier.toLowerCase(),
      orElse: () => MemberTier.gold, // Default fallback
    );
  }

  /// Copy with method for creating modified copies
  MemberCardModel copyWith({
    String? memberId,
    String? name,
    String? memberType,
    String? tier,
    int? points,
    String? validUntil,
    String? qrData,
  }) {
    return MemberCardModel(
      memberId: memberId ?? this.memberId,
      name: name ?? this.name,
      memberType: memberType ?? this.memberType,
      tier: tier ?? this.tier,
      points: points ?? this.points,
      validUntil: validUntil ?? this.validUntil,
      qrData: qrData ?? this.qrData,
    );
  }

  @override
  String toString() {
    return 'MemberCardModel(memberId: $memberId, name: $name, memberType: $memberType, tier: $tier, points: $points)';
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is MemberCardModel &&
        other.memberId == memberId &&
        other.name == name &&
        other.memberType == memberType &&
        other.tier == tier &&
        other.points == points &&
        other.validUntil == validUntil &&
        other.qrData == qrData;
  }

  @override
  int get hashCode {
    return Object.hash(
      memberId,
      name,
      memberType,
      tier,
      points,
      validUntil,
      qrData,
    );
  }
}
