class PublicParticipant {
  final String participantId;
  final String? memberId;
  final String name;
  final String? gender;
  final String? memberType;
  final num? average;
  final int handicap;
  final String? status;
  final String? paymentStatus;
  final String? comment;
  final bool isGuest;
  // 점수는 서버에서 number 또는 {score, handicap} 객체로 올 수 있음
  // rawScores: 입력 점수(핸디캡 제외)
  // handicaps: 각 게임 핸디캡(없으면 0)
  final List<int?> rawScores;
  final List<int> handicaps;

  PublicParticipant({
    required this.participantId,
    required this.memberId,
    required this.name,
    required this.gender,
    required this.memberType,
    required this.average,
    required this.handicap,
    required this.status,
    required this.paymentStatus,
    required this.comment,
    required this.isGuest,
    required this.rawScores,
    required this.handicaps,
  });

  factory PublicParticipant.fromJson(Map<String, dynamic> json, {int gameCount = 3}) {
    int parseInt(dynamic v, {int def = 0}) {
      if (v == null) return def;
      if (v is int) return v;
      return int.tryParse(v.toString()) ?? def;
    }
    num? parseNum(dynamic v) {
      if (v == null) return null;
      if (v is num) return v;
      return num.tryParse(v.toString());
    }

    final List<dynamic> src = (json['scores'] is List) ? (json['scores'] as List) : const [];
    final List<int?> raw = List<int?>.filled(gameCount, null);
    final List<int> hcs = List<int>.filled(gameCount, 0);
    for (int i = 0; i < src.length && i < gameCount; i++) {
      final el = src[i];
      if (el == null) {
        raw[i] = null;
        hcs[i] = 0;
      } else if (el is num) {
        raw[i] = el.toInt();
        hcs[i] = 0;
      } else if (el is Map) {
        final score = el['score'];
        final hc = el['handicap'];
        raw[i] = (score is num) ? score.toInt() : int.tryParse(score?.toString() ?? '');
        hcs[i] = (hc is num) ? hc.toInt() : (int.tryParse(hc?.toString() ?? '') ?? 0);
      } else {
        raw[i] = int.tryParse(el.toString());
        hcs[i] = 0;
      }
    }

    final dynamic pidRaw = json['participantId'];
    final String pid = (pidRaw != null && pidRaw.toString().isNotEmpty)
        ? pidRaw.toString()
        : (json['id']?.toString() ?? '');

    return PublicParticipant(
      participantId: pid,
      memberId: json['memberId']?.toString(),
      name: (json['name'] ?? '이름없음').toString(),
      gender: json['gender']?.toString(),
      memberType: json['memberType']?.toString(),
      average: parseNum(json['average']),
      handicap: parseInt(json['handicap'], def: 0),
      status: json['status']?.toString(),
      paymentStatus: json['paymentStatus']?.toString(),
      comment: json['comment']?.toString(),
      isGuest: json['isGuest'] == true,
      rawScores: raw,
      handicaps: hcs,
    );
  }
}

enum ParticipantStatus { pending, confirmed, canceled, unknown }
enum PaymentStatus { unpaid, paid, refunded, partial, unknown }
enum MemberType { member, guest, staff, unknown }

extension PublicParticipantEnums on PublicParticipant {
  ParticipantStatus get statusEnum {
    switch ((status ?? '').toLowerCase()) {
      case 'pending':
        return ParticipantStatus.pending;
      case 'confirmed':
        return ParticipantStatus.confirmed;
      case 'canceled':
        return ParticipantStatus.canceled;
      default:
        return ParticipantStatus.unknown;
    }
  }

  PaymentStatus get paymentEnum {
    switch ((paymentStatus ?? '').toLowerCase()) {
      case 'paid':
        return PaymentStatus.paid;
      case 'unpaid':
        return PaymentStatus.unpaid;
      case 'refunded':
        return PaymentStatus.refunded;
      case 'partial':
        return PaymentStatus.partial;
      default:
        return PaymentStatus.unknown;
    }
  }

  MemberType get memberTypeEnum {
    switch ((memberType ?? '').toLowerCase()) {
      case 'member':
        return MemberType.member;
      case 'guest':
        return MemberType.guest;
      case 'staff':
        return MemberType.staff;
      default:
        return MemberType.unknown;
    }
  }
}
