import 'package:recording_tool/features/recording/model/model_recording_context.dart';

class PlayerRegistrationListReq {
  const PlayerRegistrationListReq({required this.userId, this.status = ''});

  final String userId;
  final String status;

  Map<String, dynamic> toFormDataMap() {
    return {'userId': userId, 'status': status};
  }
}

class StreamKeyReq {
  const StreamKeyReq({
    required this.eventId,
    required this.itemId,
    required this.userId,
  });

  final String eventId;
  final String itemId;
  final String userId;

  Map<String, dynamic> toFormDataMap() {
    return {'eventId': eventId, 'itemId': itemId, 'userId': userId};
  }
}

class EventProfile {
  const EventProfile({
    required this.name,
    required this.phone,
    required this.eventTitle,
    this.avatarUrl = '',
    this.avatarLabel = '头像',
  });

  final String name;
  final String phone;
  final String eventTitle;
  final String avatarUrl;
  final String avatarLabel;
}

class EventTeamMember {
  const EventTeamMember({
    required this.userId,
    required this.name,
    required this.isLeader,
  });

  final String userId;
  final String name;
  final bool isLeader;

  factory EventTeamMember.fromJson(Map<dynamic, dynamic> json) {
    final map = Map<String, dynamic>.from(json);
    return EventTeamMember(
      userId: _readString(map, const ['userId']),
      name: _readString(map, const ['name']),
      isLeader: _readBool(map, const ['isLeader']),
    );
  }
}

class EventRegistrationList {
  const EventRegistrationList({
    required this.userId,
    required this.name,
    required this.avatar,
    required this.total,
    required this.items,
  });

  final String userId;
  final String name;
  final String avatar;
  final int total;
  final List<EventRegistrationItem> items;

  factory EventRegistrationList.fromJson(dynamic json) {
    final map = _extractObject(json);
    final rawItems = _extractList(json);
    final userId = _readString(map, const ['userId']);
    final name = _readString(map, const [
      'name',
      'playerName',
      'userName',
      'realName',
    ]);
    final avatar = _readString(map, const ['avatar', 'avatarUrl']);
    return EventRegistrationList(
      userId: userId,
      name: name,
      avatar: avatar,
      total: _readInt(map, const ['total'], fallback: rawItems.length),
      items: rawItems
          .whereType<Map>()
          .map(
            (item) => EventRegistrationItem.fromJson(
              item,
              userId: userId,
              playerName: name,
            ),
          )
          .toList(),
    );
  }

  EventProfile toProfile() {
    return EventProfile(
      name: name,
      phone: '',
      eventTitle: items.isEmpty ? '赛事信息' : items.first.eventName,
      avatarUrl: avatar,
    );
  }
}

class EventRegistrationItem {
  const EventRegistrationItem({
    required this.eventId,
    required this.itemId,
    required this.scheduleId,
    required this.eventName,
    required this.itemName,
    required this.groupName,
    required this.matchPlace,
    required this.allowByeMatch,

    this.matchStartTime = '',
    this.matchEndTime = '',
    this.completed = false,
    this.opponentId = '',
    this.opponentName = '',
    this.teamMembers = const [],
    this.userId = '',
    this.playerName = '',
    this.playerPhone = '',
    this.playerNo = '',
  });

  final String eventId;
  final String itemId;
  final String scheduleId;
  final String eventName;
  final String itemName;
  final String groupName;
  final String matchPlace;
  final String matchStartTime;
  final String matchEndTime;
  final bool completed;
  final String opponentId;
  final String opponentName;
  final List<EventTeamMember> teamMembers;
  final String playerNo;
  final int allowByeMatch;

  /// 来自报名列表父级，不在 item JSON 内
  final String userId;
  final String playerName;
  final String playerPhone;

  String get scheduleTime => _formatScheduleTime(matchStartTime, matchEndTime);

  String? get statusLabel => completed ? '已完成' : null;

  EventTeamMember? get teamLeader {
    for (final member in teamMembers) {
      if (member.isLeader) return member;
    }
    return teamMembers.isEmpty ? null : teamMembers.first;
  }

  factory EventRegistrationItem.fromJson(
    Map<dynamic, dynamic> json, {
    String userId = '',
    String playerName = '',
  }) {
    final map = Map<String, dynamic>.from(json);
    final startTime = _readString(map, const ['matchStartTime']);
    final endTime = _readString(map, const ['matchEndTime']);
    final teamMembersRaw = map['teamMembers'];
    return EventRegistrationItem(
      eventId: _readString(map, const ['eventId']),
      itemId: _readString(map, const ['itemId']),
      scheduleId: _readString(map, const ['scheduleId']),
      eventName: _readString(map, const ['eventName'], fallback: '赛事信息'),
      itemName: _readString(map, const ['itemName'], fallback: '未命名项目'),
      groupName: _readString(map, const ['groupName']),
      matchPlace: _readString(map, const ['matchPlace']),
      matchStartTime: startTime,
      matchEndTime: endTime,
      completed: _readBool(map, const ['completed']),
      opponentId: _readString(map, const ['opponentId']),
      opponentName: _readString(map, const ['opponentName']),
      teamMembers: teamMembersRaw is List
          ? teamMembersRaw
                .whereType<Map>()
                .map(EventTeamMember.fromJson)
                .toList(growable: false)
          : const [],
      userId: userId,
      playerName: playerName,
      playerNo: _readString(map, const ['playerNo']),
      allowByeMatch: _readInt(map, const ['allowByeMatch']),
    );
  }

  EventProfile toProfile() {
    return EventProfile(
      name: playerName,
      phone: playerPhone,
      eventTitle: eventName,
    );
  }

  RecordingContext toRecordingContext({EventProfile? profile}) {
    return RecordingContext(
      eventTitle: eventName,
      matchName: itemName,
      group: groupName,
      venue: matchPlace,
      time: scheduleTime,
      playerName: profile?.name ?? playerName,
      playerPhone: profile?.phone ?? playerPhone,
      status: statusLabel,
    );
  }
}

class StreamKeyResponse {
  const StreamKeyResponse({required this.rawData});

  final Map<String, dynamic> rawData;

  factory StreamKeyResponse.fromJson(dynamic json) {
    if (json is Map) {
      return StreamKeyResponse(rawData: Map<String, dynamic>.from(json));
    }
    return StreamKeyResponse(rawData: {'value': json});
  }

  @override
  String toString() => rawData.toString();
}

List<dynamic> _extractList(dynamic json) {
  if (json is List) return json;
  if (json is Map) {
    for (final key in const ['records', 'items', 'rows', 'list', 'data']) {
      final value = json[key];
      if (value is List) return value;
      if (value is Map) {
        final nested = _extractList(value);
        if (nested.isNotEmpty) return nested;
      }
    }
  }
  return const [];
}

Map<String, dynamic> _extractObject(dynamic json) {
  if (json is Map) {
    final map = Map<String, dynamic>.from(json);
    final data = map['data'];
    if (data is Map) return Map<String, dynamic>.from(data);
    return map;
  }
  return const {};
}

String _readString(
  Map<String, dynamic> map,
  List<String> keys, {
  String fallback = '',
}) {
  return _readNullableString(map, keys) ?? fallback;
}

String _formatScheduleTime(String startTime, String endTime) {
  if (startTime.isNotEmpty && endTime.isNotEmpty) {
    return '$startTime-$endTime';
  }
  if (startTime.isNotEmpty) return startTime;
  if (endTime.isNotEmpty) return endTime;
  return '';
}

int _readInt(Map<String, dynamic> map, List<String> keys, {int fallback = 0}) {
  for (final key in keys) {
    final value = _findValue(map, key);
    if (value is int) return value;
    if (value is num) return value.toInt();
    if (value is String) {
      final parsed = int.tryParse(value.trim());
      if (parsed != null) return parsed;
    }
  }
  return fallback;
}

bool _readBool(Map<String, dynamic> map, List<String> keys) {
  for (final key in keys) {
    final value = _findValue(map, key);
    if (value is bool) return value;
    if (value is num) return value != 0;
    if (value is String) {
      final text = value.trim().toLowerCase();
      if (text == 'true' || text == '1') return true;
      if (text == 'false' || text == '0') return false;
    }
  }
  return false;
}

String? _readNullableString(Map<String, dynamic> map, List<String> keys) {
  for (final key in keys) {
    final value = _findValue(map, key);
    if (value == null) continue;
    final text = value.toString().trim();
    if (text.isNotEmpty) return text;
  }
  return null;
}

dynamic _findValue(dynamic value, String key) {
  if (value is Map) {
    if (value.containsKey(key)) return value[key];
    for (final child in value.values) {
      final found = _findValue(child, key);
      if (found != null) return found;
    }
  }
  if (value is List) {
    for (final child in value) {
      final found = _findValue(child, key);
      if (found != null) return found;
    }
  }
  return null;
}
