import '../models/match.dart';

/// Lato che ha vinto set o partita.
enum ScoringSide { home, away }

/// Regole punteggio (pallavolo di default, campi sovrascrivibili per tornei).
class MatchScoringRules {
  const MatchScoringRules({
    required this.setsToWin,
    this.pointsPerSet = 25,
    this.pointsDecidingSet = 15,
    this.minPointLead = 2,
  });

  final int setsToWin;
  final int pointsPerSet;
  final int pointsDecidingSet;
  final int minPointLead;

  int get maxSets => (setsToWin * 2) - 1;

  factory MatchScoringRules.fromMatch(MatchModel match) {
    final overrides = match.scoringRules;
    return MatchScoringRules(
      setsToWin: match.setsToWin,
      pointsPerSet: overrides?['points_per_set'] as int? ?? 25,
      pointsDecidingSet: overrides?['points_deciding_set'] as int? ?? 15,
      minPointLead: overrides?['min_point_lead'] as int? ?? 2,
    );
  }

  Map<String, dynamic> toJson() => {
        'points_per_set': pointsPerSet,
        'points_deciding_set': pointsDecidingSet,
        'min_point_lead': minPointLead,
      };

  /// Punti necessari per chiudere il set corrente.
  int pointsTarget(int currentSet) {
    if (currentSet >= maxSets) return pointsDecidingSet;
    return pointsPerSet;
  }

  /// Chi ha vinto il set in corso in base ai punti (null se ancora aperto).
  ScoringSide? setWinnerFromPoints({
    required int homePoints,
    required int awayPoints,
    required int currentSet,
  }) {
    final target = pointsTarget(currentSet);
    final lead = minPointLead;
    if (homePoints >= target && homePoints - awayPoints >= lead) {
      return ScoringSide.home;
    }
    if (awayPoints >= target && awayPoints - homePoints >= lead) {
      return ScoringSide.away;
    }
    return null;
  }

  bool isMatchOver({required int homeSets, required int awaySets}) {
    return homeSets >= setsToWin || awaySets >= setsToWin;
  }

  ScoringSide? matchWinner({required int homeSets, required int awaySets}) {
    if (homeSets >= setsToWin) return ScoringSide.home;
    if (awaySets >= setsToWin) return ScoringSide.away;
    return null;
  }
}
