import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:data_table_2/data_table_2.dart';
import 'package:lanebow/models/public_event.dart';
import 'package:lanebow/models/public_participant.dart';
import 'package:lanebow/models/public_team.dart';
import 'package:lanebow/widgets/public_user_widgets.dart';
import 'package:lanebow/theme/badges.dart';

class PersonalCardView extends StatelessWidget {
  final PublicEvent? event;
  final List<PublicParticipant> participants;
  final Map<String, Map> partRankMap;
  final bool canInputScore;
  final List<PublicTeam> teams;
  final String Function(String pid, int gameNumber) keyFor;
  final Widget Function(String key) stateIcon;
  final void Function(PublicParticipant p, int gameNumber, int value)
  saveInlineScore;
  final void Function(PublicParticipant p, int gameNumber, int value)
  saveInlineHandicap;
  final num? Function(List<int?> rawScores) calcAvg;
  final int? Function(String pid, Map<String, Map> map) rankForParticipant;

  const PersonalCardView({
    super.key,
    required this.event,
    required this.participants,
    required this.partRankMap,
    required this.canInputScore,
    required this.teams,
    required this.keyFor,
    required this.stateIcon,
    required this.saveInlineScore,
    required this.saveInlineHandicap,
    required this.calcAvg,
    required this.rankForParticipant,
  });

  @override
  Widget build(BuildContext context) {
    // 팀의 per-game 핸디 우선 적용을 위해 map 빌드
    final Map<String, List<int>> teamHcByPid = {};
    for (final t in teams) {
      for (final m in t.members) {
        if ((m.participantId ?? '').isNotEmpty) {
          teamHcByPid[m.participantId!] = List<int>.from(m.handicaps);
        }
      }
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(height: 8),
        const Text(
          '참가자',
          style: TextStyle(fontWeight: FontWeight.bold),
          key: Key('section_participants'),
        ),
        Text('총 ${participants.length}명', key: const Key('participants_count')),
        const SizedBox(height: 8),
        Expanded(
          child: Card(
            child: participants.isEmpty
                ? const ListTile(
                    key: Key('empty_participants'),
                    title: Text('참가자가 없습니다'),
                  )
                : ListView.separated(
                    padding: EdgeInsets.zero,
                    itemCount: participants.length,
                    separatorBuilder: (_, i) => const Padding(
                      padding: EdgeInsets.symmetric(horizontal: 8),
                      child: Divider(height: 12, thickness: 0.6),
                    ),
                    itemBuilder: (_, i) {
                      final p = participants[i];
                      return ListTile(
                        contentPadding: const EdgeInsets.symmetric(
                          horizontal: 8,
                          vertical: 4,
                        ),
                        key: Key('participant_tile_${p.participantId}'),
                        title: PublicUserNameRow(
                          name: p.name,
                          gender: p.gender,
                          memberType: p.memberType,
                          userHandicap: p.handicap,
                          userAverage: p.average,
                          rank: rankForParticipant(
                            p.participantId,
                            partRankMap,
                          ),
                        ),
                        subtitle: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            PublicUserChipsRow(
                              status: p.status,
                              paymentStatus: p.paymentStatus,
                              memberType: p.memberType,
                            ),
                            if (event != null)
                              Padding(
                                padding: const EdgeInsets.only(top: 8),
                                child: PublicUserGameEditors(
                                  gameCount: event!.gameCount,
                                  participantId: p.participantId,
                                  rawScores: p.rawScores,
                                  handicaps:
                                      teamHcByPid[p.participantId] ??
                                      p.handicaps,
                                  enabled: canInputScore,
                                  keyFor: keyFor,
                                  stateIcon: stateIcon,
                                  onScoreChanged: (g, val) =>
                                      saveInlineScore(p, g, val),
                                  onHandicapChanged: (g, val) =>
                                      saveInlineHandicap(p, g, val),
                                  eventAverage: calcAvg(
                                    p.rawScores,
                                  )?.toDouble(),
                                  memberHandicap: p.handicap,
                                ),
                              ),
                          ],
                        ),
                      );
                    },
                  ),
          ),
        ),
      ],
    );
  }
}

class PersonalTableView extends StatefulWidget {
  final PublicEvent event;
  final List<PublicParticipant> participants;
  final bool canInputScore;
  final List<PublicTeam> teams;
  final void Function(PublicParticipant p, int gameNumber, int value)
  saveInlineScore;
  final void Function(PublicParticipant p, int gameNumber, int value)
  saveInlineHandicap;
  final Map<String, Map>? partRankMap;
  final int? Function(String pid, Map<String, Map> map)? rankForParticipant;

  const PersonalTableView({
    super.key,
    required this.event,
    required this.participants,
    required this.canInputScore,
    required this.teams,
    required this.saveInlineScore,
    required this.saveInlineHandicap,
    this.partRankMap,
    this.rankForParticipant,
  });

  @override
  State<PersonalTableView> createState() => _PersonalTableViewState();
}

class _PersonalTableViewState extends State<PersonalTableView> {
  int? _sortColumnIndex = 0;
  bool _sortAscending = true;
  List<PublicParticipant> _rows = [];

  Future<void> _openEditSheet({
    required PublicParticipant participant,
    required int gameNumber,
    required int? currentRaw,
    required int currentHc,
  }) async {
    final rawCtrl = TextEditingController(
      text: currentRaw == null || currentRaw == 0 ? '' : '$currentRaw',
    );
    final hcCtrl = TextEditingController(
      text: currentHc == 0 ? '' : '$currentHc',
    );
    Future<void> _commit(BuildContext ctx) async {
      FocusScope.of(ctx).unfocus();
      final rawVal = int.tryParse(rawCtrl.text.trim()) ?? 0;
      final hcVal = int.tryParse(hcCtrl.text.trim()) ?? 0;
      final prevRaw = currentRaw ?? 0;
      final prevHc = currentHc;
      final changedRaw = rawVal != prevRaw;
      final changedHc = hcVal != prevHc;

      if (changedRaw && !changedHc) {
        widget.saveInlineScore(participant, gameNumber, rawVal);
      } else if (!changedRaw && changedHc) {
        widget.saveInlineHandicap(participant, gameNumber, hcVal);
      } else if (changedRaw && changedHc) {
        // Debouncer key is the same for score/handicap; sequence to avoid cancellation
        widget.saveInlineScore(participant, gameNumber, rawVal);
        await Future.delayed(const Duration(milliseconds: 650));
        widget.saveInlineHandicap(participant, gameNumber, hcVal);
      }
      Navigator.pop(ctx, true);
    }

    final res = await showModalBottomSheet<bool>(
      context: context,
      isScrollControlled: true,
      builder: (ctx) {
        return Padding(
          padding: EdgeInsets.only(
            bottom: MediaQuery.of(ctx).viewInsets.bottom,
            left: 16,
            right: 16,
            top: 16,
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                children: [
                  Expanded(
                    child: TextFormField(
                      controller: rawCtrl,
                      keyboardType: TextInputType.number,
                      textInputAction: TextInputAction.done,
                      inputFormatters: [FilteringTextInputFormatter.digitsOnly],
                      decoration: const InputDecoration(labelText: '점수'),
                      onFieldSubmitted: (_) => _commit(ctx),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: TextFormField(
                      controller: hcCtrl,
                      keyboardType: TextInputType.number,
                      textInputAction: TextInputAction.done,
                      inputFormatters: [FilteringTextInputFormatter.digitsOnly],
                      decoration: const InputDecoration(labelText: '핸디'),
                      onFieldSubmitted: (_) => _commit(ctx),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 12),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  TextButton(
                    onPressed: () => Navigator.pop(ctx, false),
                    child: const Text('취소'),
                  ),
                  const SizedBox(width: 8),
                  ElevatedButton(
                    onPressed: () => _commit(ctx),
                    child: const Text('저장'),
                  ),
                ],
              ),
              const SizedBox(height: 12),
            ],
          ),
        );
      },
    );
    if (res == true) {
      setState(() {});
    }
  }

  @override
  void initState() {
    super.initState();
    _rows = List.of(widget.participants);
    final rf = widget.rankForParticipant;
    final prm = widget.partRankMap;
    if (rf != null && prm != null) {
      _rows.sort((a, b) {
        final ra = (rf(a.participantId, prm) ?? 99999);
        final rb = (rf(b.participantId, prm) ?? 99999);
        return ra.compareTo(rb);
      });
    }
  }

  @override
  void didUpdateWidget(covariant PersonalTableView oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (!identical(oldWidget.participants, widget.participants) ||
        oldWidget.participants.length != widget.participants.length) {
      _rows = List.of(widget.participants);
      final rf = widget.rankForParticipant;
      final prm = widget.partRankMap;
      if (rf != null && prm != null) {
        _rows.sort((a, b) {
          final ra = (rf(a.participantId, prm) ?? 99999);
          final rb = (rf(b.participantId, prm) ?? 99999);
          return ra.compareTo(rb);
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final event = widget.event;
    final participants = widget.participants;
    final bool enabled = widget.canInputScore && (event.isActive == true);
    final teams = widget.teams;
    final partRankMap = widget.partRankMap;
    final rankForParticipant = widget.rankForParticipant;

    final List<PublicParticipant> rows = _rows;
    final Map<String, List<int>> teamHcByPid = {};
    final Map<String, String> teamLabelByPid = {};
    for (final t in teams) {
      for (final m in t.members) {
        if ((m.participantId ?? '').isNotEmpty) {
          teamHcByPid[m.participantId!] = List<int>.from(m.handicaps);
          teamLabelByPid[m.participantId!] = '팀 ${t.teamNumber}';
        }
      }
    }

    const double headH = 40.0;
    const double rowH = 100.0;

    int rawAt(List<int?> raw, int g) =>
        (g - 1 >= 0 && g - 1 < raw.length && raw[g - 1] != null)
        ? raw[g - 1]!
        : 0;
    bool hasRaw(List<int?> raw, int g) =>
        (g - 1 >= 0 && g - 1 < raw.length && raw[g - 1] != null);
    int hcAt(List<int> perGame, int? memberHc, int g) {
      int hv = (g - 1 >= 0 && g - 1 < perGame.length) ? perGame[g - 1] : 0;
      if (hv == 0 && (memberHc ?? 0) != 0) return memberHc!;
      return hv;
    }

    int overallRawTotal(List<int?> raw, int gameCount) {
      int s = 0;
      for (int g = 1; g <= gameCount; g++) {
        if (hasRaw(raw, g)) s += rawAt(raw, g);
      }
      return s;
    }

    int overallWithHcTotal(
      List<int?> raw,
      List<int> perGame,
      int? memberHc,
      int gameCount,
    ) {
      int s = 0;
      for (int g = 1; g <= gameCount; g++) {
        if (hasRaw(raw, g)) s += rawAt(raw, g) + hcAt(perGame, memberHc, g);
      }
      return s;
    }

    double? avgRaw(List<int?> raw, int gameCount) {
      int count = 0, sum = 0;
      for (int g = 1; g <= gameCount; g++) {
        if (hasRaw(raw, g)) {
          sum += rawAt(raw, g);
          count++;
        }
      }
      if (count == 0) return null;
      return sum / count;
    }

    double? avgWithHc(
      List<int?> raw,
      List<int> perGame,
      int? memberHc,
      int gameCount,
    ) {
      int count = 0, sum = 0;
      for (int g = 1; g <= gameCount; g++) {
        if (hasRaw(raw, g)) {
          sum += rawAt(raw, g) + hcAt(perGame, memberHc, g);
          count++;
        }
      }
      if (count == 0) return null;
      return sum / count;
    }

    Color valueColor(num v) => v >= 200 ? Colors.red : Colors.black87;
    int playedGames(List<int?> raw, int gameCount) {
      int c = 0;
      for (int g = 1; g <= gameCount; g++) {
        if (hasRaw(raw, g)) c++;
      }
      return c;
    }

    Color totalColor(int total, int nGames) {
      if (nGames <= 0) return Colors.blueGrey;
      final thresh = 200 * nGames;
      return total >= thresh ? Colors.red : Colors.blueGrey;
    }

    Widget genderIcon(String? gender) {
      final g = (gender ?? '').toLowerCase();
      final isFemale = g == 'female' || g == 'f' || g == '여' || g == '여성';
      final icon = isFemale ? Icons.female : Icons.male;
      final color = isFemale ? Colors.pink : Colors.blue;
      return CircleAvatar(
        radius: 8,
        backgroundColor: color.withValues(alpha: 0.1),
        child: Icon(icon, size: 12, color: color),
      );
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(height: 8),
        const Text(
          '개인별 (표 보기)',
          style: TextStyle(fontWeight: FontWeight.bold),
          key: Key('participants_table_title'),
        ),
        Text(
          '총 ${participants.length}명',
          key: const Key('participants_table_count'),
        ),
        const SizedBox(height: 8),
        Expanded(
          child: DataTable2(
            headingRowHeight: headH,
            horizontalMargin: 0,
            columnSpacing: 8,
            dataRowHeight: rowH,
            minWidth: 600,
            fixedTopRows: 1,
            fixedLeftColumns: 2,
            sortColumnIndex: _sortColumnIndex,
            sortAscending: _sortAscending,
            border: TableBorder.all(color: Colors.black12, width: 0.5),
            columns: [
              DataColumn2(
                fixedWidth: 55,
                label: const Center(child: Text('순위')),
                onSort: (i, asc) {
                  setState(() {
                    _sortColumnIndex = i;
                    _sortAscending = asc;
                    rows.sort((a, b) {
                      final ra =
                          (rankForParticipant?.call(
                            a.participantId,
                            partRankMap ?? const {},
                          ) ??
                          99999);
                      final rb =
                          (rankForParticipant?.call(
                            b.participantId,
                            partRankMap ?? const {},
                          ) ??
                          99999);
                      return asc ? ra.compareTo(rb) : rb.compareTo(ra);
                    });
                  });
                },
                numeric: true,
              ),
              DataColumn2(
                size: ColumnSize.L,
                label: const Text('이름'),
                onSort: (i, asc) {
                  setState(() {
                    _sortColumnIndex = i;
                    _sortAscending = asc;
                    rows.sort(
                      (a, b) => asc
                          ? a.name.compareTo(b.name)
                          : b.name.compareTo(a.name),
                    );
                  });
                },
              ),
              DataColumn2(
                size: ColumnSize.S,
                label: const Text('팀'),
                onSort: (i, asc) {
                  setState(() {
                    _sortColumnIndex = i;
                    _sortAscending = asc;
                    rows.sort((a, b) {
                      final ta = teamLabelByPid[a.participantId] ?? '';
                      final tb = teamLabelByPid[b.participantId] ?? '';
                      return asc ? ta.compareTo(tb) : tb.compareTo(ta);
                    });
                  });
                },
              ),
              for (int g = 1; g <= event.gameCount; g++)
                DataColumn(
                  label: Text('${g}G'),
                  onSort: (i, asc) {
                    setState(() {
                      _sortColumnIndex = i;
                      _sortAscending = asc;
                      rows.sort((a, b) {
                        final perA =
                            teamHcByPid[a.participantId] ?? a.handicaps;
                        final perB =
                            teamHcByPid[b.participantId] ?? b.handicaps;
                        final sa = (hasRaw(a.rawScores, g)
                            ? rawAt(a.rawScores, g) + hcAt(perA, a.handicap, g)
                            : -999999);
                        final sb = (hasRaw(b.rawScores, g)
                            ? rawAt(b.rawScores, g) + hcAt(perB, b.handicap, g)
                            : -999999);
                        return asc ? sa.compareTo(sb) : sb.compareTo(sa);
                      });
                    });
                  },
                  numeric: true,
                ),
              DataColumn(
                label: const Text('총점'),
                onSort: (i, asc) {
                  setState(() {
                    _sortColumnIndex = i;
                    _sortAscending = asc;
                    rows.sort((a, b) {
                      final perGameA =
                          teamHcByPid[a.participantId] ?? a.handicaps;
                      final perGameB =
                          teamHcByPid[b.participantId] ?? b.handicaps;
                      final ta = overallWithHcTotal(
                        a.rawScores,
                        perGameA,
                        a.handicap,
                        event.gameCount,
                      );
                      final tb = overallWithHcTotal(
                        b.rawScores,
                        perGameB,
                        b.handicap,
                        event.gameCount,
                      );
                      return asc ? ta.compareTo(tb) : tb.compareTo(ta);
                    });
                  });
                },
                numeric: true,
              ),
              DataColumn(
                label: const Text('에버리지'),
                onSort: (i, asc) {
                  setState(() {
                    _sortColumnIndex = i;
                    _sortAscending = asc;
                    rows.sort((a, b) {
                      final perGameA =
                          teamHcByPid[a.participantId] ?? a.handicaps;
                      final perGameB =
                          teamHcByPid[b.participantId] ?? b.handicaps;
                      final aa =
                          (avgWithHc(
                            a.rawScores,
                            perGameA,
                            a.handicap,
                            event.gameCount,
                          ) ??
                          0);
                      final ab =
                          (avgWithHc(
                            b.rawScores,
                            perGameB,
                            b.handicap,
                            event.gameCount,
                          ) ??
                          0);
                      return asc ? aa.compareTo(ab) : ab.compareTo(aa);
                    });
                  });
                },
                numeric: true,
              ),
            ],
            rows: [
              for (final p in rows)
                DataRow(
                  cells: [
                    DataCell(
                      SizedBox(
                        width: 28,
                        child: Center(
                          child: Text(
                            (rankForParticipant?.call(
                                      p.participantId,
                                      partRankMap ?? const {},
                                    ) ??
                                    0)
                                .toString(),
                            style: const TextStyle(fontWeight: FontWeight.w600),
                          ),
                        ),
                      ),
                    ),
                    DataCell(
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Row(
                            children: [
                              genderIcon(p.gender),
                              const SizedBox(width: 6),
                              Flexible(
                                child: Text(
                                  p.name,
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                            ],
                          ),
                          const SizedBox(height: 2),
                          Builder(
                            builder: (context) {
                              final String? avgText = (p.average == null)
                                  ? null
                                  : ((p.average is double)
                                            ? (p.average as double)
                                            : (p.average as num).toDouble())
                                        .toStringAsFixed(1);
                              final String? hcText = (p.handicap == 0)
                                  ? null
                                  : (p.handicap > 0
                                        ? '+${p.handicap}'
                                        : '${p.handicap}');
                              return Wrap(
                                spacing: 4,
                                runSpacing: 2,
                                children: [
                                  if (hcText != null)
                                    Chip(
                                      label: Text(
                                        hcText,
                                        style: const TextStyle(
                                          fontSize: 10,
                                          height: 1.0,
                                        ),
                                      ),
                                      backgroundColor: BadgeStyles.successBg,
                                      padding: EdgeInsets.zero,
                                      labelPadding: const EdgeInsets.symmetric(
                                        horizontal: 4,
                                        vertical: 0,
                                      ),
                                      materialTapTargetSize:
                                          MaterialTapTargetSize.shrinkWrap,
                                      visualDensity: const VisualDensity(
                                        horizontal: -4,
                                        vertical: -4,
                                      ),
                                    ),
                                  if (avgText != null)
                                    Chip(
                                      label: Text(
                                        avgText,
                                        style: const TextStyle(
                                          fontSize: 10,
                                          height: 1.0,
                                        ),
                                      ),
                                      backgroundColor: BadgeStyles.primaryBg,
                                      padding: EdgeInsets.zero,
                                      labelPadding: const EdgeInsets.symmetric(
                                        horizontal: 4,
                                        vertical: 0,
                                      ),
                                      materialTapTargetSize:
                                          MaterialTapTargetSize.shrinkWrap,
                                      visualDensity: const VisualDensity(
                                        horizontal: -4,
                                        vertical: -4,
                                      ),
                                    ),
                                ],
                              );
                            },
                          ),
                        ],
                      ),
                    ),
                    DataCell(
                      Text(
                        teamLabelByPid[p.participantId] ?? '',
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    for (int g = 1; g <= event.gameCount; g++)
                      DataCell(
                        Builder(
                          builder: (context) {
                            final perGame =
                                teamHcByPid[p.participantId] ?? p.handicaps;
                            final effHc = hcAt(perGame, p.handicap, g);
                            final has = hasRaw(p.rawScores, g);
                            if (!has) {
                              return const SizedBox.expand(
                                child: Center(child: Text('')),
                              );
                            }
                            final raw = rawAt(p.rawScores, g);
                            final sum = raw + effHc;
                            if (effHc == 0) {
                              return SizedBox.expand(
                                child: Center(
                                  child: Text(
                                    '$raw',
                                    style: const TextStyle(
                                      fontWeight: FontWeight.w700,
                                      fontSize: 18,
                                      color: Colors.black87,
                                    ),
                                  ),
                                ),
                              );
                            }
                            return SizedBox.expand(
                              child: Stack(
                                children: [
                                  Positioned.fill(
                                    child: CustomPaint(
                                      painter: _DiagonalSlashPainter(
                                        Colors.black26,
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.topLeft,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        left: 2,
                                        top: 2,
                                      ),
                                      child: Column(
                                        crossAxisAlignment:
                                            CrossAxisAlignment.start,
                                        mainAxisSize: MainAxisSize.min,
                                        children: [
                                          Text(
                                            '$raw',
                                            style: const TextStyle(
                                              fontWeight: FontWeight.w600,
                                              color: Colors.black87,
                                            ),
                                          ),
                                          Text(
                                            '+$effHc',
                                            style: TextStyle(
                                              fontWeight: FontWeight.w600,
                                              color: Colors.grey.shade700,
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.bottomRight,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        right: 2,
                                        bottom: 2,
                                      ),
                                      child: Text(
                                        '$sum',
                                        textAlign: TextAlign.right,
                                        style: TextStyle(
                                          fontWeight: FontWeight.w700,
                                          fontSize: 18,
                                          color: valueColor(sum),
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            );
                          },
                        ),
                        onTap: enabled
                            ? () {
                                final perGame = teamHcByPid[p.participantId] ?? p.handicaps;
                                final hc = hcAt(perGame, p.handicap, g);
                                final has = hasRaw(p.rawScores, g);
                                final current = has ? rawAt(p.rawScores, g) : null;
                                _openEditSheet(
                                  participant: p,
                                  gameNumber: g,
                                  currentRaw: current,
                                  currentHc: hc,
                                );
                              }
                            : null,
                      ),
                    DataCell(
                      Builder(
                        builder: (context) {
                          final perGame =
                              teamHcByPid[p.participantId] ?? p.handicaps;
                          final raw = overallRawTotal(
                            p.rawScores,
                            event.gameCount,
                          );
                          final withHc = overallWithHcTotal(
                            p.rawScores,
                            perGame,
                            p.handicap,
                            event.gameCount,
                          );
                          final n = playedGames(p.rawScores, event.gameCount);
                          if (withHc != raw) {
                            return SizedBox.expand(
                              child: Stack(
                                children: [
                                  Positioned.fill(
                                    child: CustomPaint(
                                      painter: _DiagonalSlashPainter(
                                        Colors.black26,
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.topLeft,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        left: 2,
                                        top: 2,
                                      ),
                                      child: Text(
                                        '$raw',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w600,
                                          color: totalColor(raw, n),
                                        ),
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.bottomRight,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        right: 2,
                                        bottom: 2,
                                      ),
                                      child: Text(
                                        '$withHc',
                                        textAlign: TextAlign.right,
                                        style: TextStyle(
                                          fontWeight: FontWeight.w700,
                                          fontSize: 18,
                                          color: totalColor(withHc, n),
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            );
                          }
                          return SizedBox.expand(
                            child: Center(
                              child: Text(
                                '$raw',
                                style: TextStyle(
                                  fontWeight: FontWeight.w700,
                                  fontSize: 18,
                                  color: totalColor(raw, n),
                                ),
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                    DataCell(
                      Builder(
                        builder: (context) {
                          final perGame =
                              teamHcByPid[p.participantId] ?? p.handicaps;
                          final rawAvg =
                              (avgRaw(p.rawScores, event.gameCount) ?? 0)
                                  .toStringAsFixed(1);
                          final withHcAvg =
                              (avgWithHc(
                                        p.rawScores,
                                        perGame,
                                        p.handicap,
                                        event.gameCount,
                                      ) ??
                                      0)
                                  .toStringAsFixed(1);
                          final avgNum =
                              double.tryParse(withHcAvg) ??
                              double.tryParse(rawAvg) ??
                              0;
                          if (withHcAvg != rawAvg) {
                            return SizedBox.expand(
                              child: Stack(
                                children: [
                                  Positioned.fill(
                                    child: CustomPaint(
                                      painter: _DiagonalSlashPainter(
                                        Colors.black26,
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.topLeft,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        left: 2,
                                        top: 2,
                                      ),
                                      child: Text(
                                        rawAvg,
                                        style: TextStyle(
                                          fontWeight: FontWeight.w600,
                                          color: valueColor(
                                            double.tryParse(rawAvg) ?? 0,
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                  Align(
                                    alignment: Alignment.bottomRight,
                                    child: Padding(
                                      padding: const EdgeInsets.only(
                                        right: 2,
                                        bottom: 2,
                                      ),
                                      child: Text(
                                        withHcAvg,
                                        textAlign: TextAlign.right,
                                        style: TextStyle(
                                          fontWeight: FontWeight.w700,
                                          fontSize: 18,
                                          color: valueColor(
                                            double.tryParse(withHcAvg) ?? 0,
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            );
                          }
                          return SizedBox.expand(
                            child: Center(
                              child: Text(
                                rawAvg,
                                style: TextStyle(
                                  fontWeight: FontWeight.w700,
                                  fontSize: 18,
                                  color: valueColor(avgNum),
                                ),
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                  ],
                ),
            ],
          ),
        ),
      ],
    );
  }
}

class _DiagonalSlashPainter extends CustomPainter {
  final Color color;
  const _DiagonalSlashPainter(this.color);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 1.0
      ..style = PaintingStyle.stroke;
    // Draw diagonal from bottom-left to top-right
    canvas.drawLine(Offset(0, size.height), Offset(size.width, 0), paint);
  }

  @override
  bool shouldRepaint(covariant _DiagonalSlashPainter oldDelegate) {
    return oldDelegate.color != color;
  }
}
