import 'package:flutter_test/flutter_test.dart';
import 'package:lanebow/models/score_model.dart';

void main() {
  group('Score 모델 테스트', () {
    test('fromJson 메서드가 JSON 데이터를 올바르게 변환해야 함', () {
      // given
      final json = {
        'id': 'test_id',
        'memberId': 'test_member_id',
        'eventId': 'test_event_id',
        'clubId': 'test_club_id',
        'frames': [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
        'totalScore': 55,
        'date': '2023-01-01T12:00:00.000Z',
        'notes': '테스트 노트',
        'participantName': '테스트 참가자',
      };

      // when
      final score = Score.fromJson(json);

      // then
      expect(score.id, 'test_id');
      expect(score.memberId, 'test_member_id');
      expect(score.eventId, 'test_event_id');
      expect(score.clubId, 'test_club_id');
      expect(score.frames, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
      expect(score.totalScore, 55);
      expect(score.date, DateTime.parse('2023-01-01T12:00:00.000Z'));
      expect(score.notes, '테스트 노트');
      expect(score.participantName, '테스트 참가자');
    });

    test('fromJson 메서드가 일부 필드가 null인 JSON 데이터를 처리해야 함', () {
      // given
      final json = {
        'id': 'test_id',
        'memberId': 'test_member_id',
        'eventId': 'test_event_id',
        'clubId': 'test_club_id',
        'frames': [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
        'totalScore': 55,
        'date': '2023-01-01T12:00:00.000Z',
        // notes와 participantName은 생략
      };

      // when
      final score = Score.fromJson(json);

      // then
      expect(score.id, 'test_id');
      expect(score.memberId, 'test_member_id');
      expect(score.eventId, 'test_event_id');
      expect(score.clubId, 'test_club_id');
      expect(score.frames, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
      expect(score.totalScore, 55);
      expect(score.date, DateTime.parse('2023-01-01T12:00:00.000Z'));
      expect(score.notes, null);
      expect(score.participantName, null);
    });

    test('fromJson 메서드가 필수 필드가 null인 경우 기본값을 설정해야 함', () {
      // given
      final json = {
        // 필수 필드가 null이거나 누락된 경우
        'id': null,
        'memberId': null,
        'eventId': null,
        'clubId': null,
        'frames': null,
        'totalScore': null,
        'date': null,
      };

      // when
      final score = Score.fromJson(json);

      // then
      expect(score.id, '');
      expect(score.memberId, '');
      expect(score.eventId, '');
      expect(score.clubId, '');
      expect(score.frames, []);
      expect(score.totalScore, 0);
      expect(score.date.year, DateTime.now().year); // 현재 날짜로 설정되었는지 확인
      expect(score.notes, null);
      expect(score.participantName, null);
    });

    test('toJson 메서드가 Score 객체를 JSON으로 올바르게 변환해야 함', () {
      // given
      final score = Score(
        id: 'test_id',
        memberId: 'test_member_id',
        eventId: 'test_event_id',
        clubId: 'test_club_id',
        frames: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
        totalScore: 55,
        date: DateTime.parse('2023-01-01T12:00:00.000Z'),
        notes: '테스트 노트',
        participantName: '테스트 참가자',
      );

      // when
      final json = score.toJson();

      // then
      expect(json['id'], 'test_id');
      expect(json['memberId'], 'test_member_id');
      expect(json['eventId'], 'test_event_id');
      expect(json['clubId'], 'test_club_id');
      expect(json['frames'], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
      expect(json['totalScore'], 55);
      expect(json['date'], '2023-01-01T12:00:00.000Z');
      expect(json['notes'], '테스트 노트');
      expect(json['participantName'], '테스트 참가자');
    });
  });

  group('ScoreStatistics 모델 테스트', () {
    test('fromJson 메서드가 JSON 데이터를 올바르게 변환해야 함', () {
      // given
      final json = {
        'average': 150.5,
        'highScore': 200,
        'lowScore': 100,
        'gamesPlayed': 10,
        'additionalStats': {
          'strikes': 5,
          'spares': 3,
        },
      };

      // when
      final stats = ScoreStatistics.fromJson(json);

      // then
      expect(stats.average, 150.5);
      expect(stats.highScore, 200);
      expect(stats.lowScore, 100);
      expect(stats.gamesPlayed, 10);
      expect(stats.additionalStats?['strikes'], 5);
      expect(stats.additionalStats?['spares'], 3);
    });

    test('fromJson 메서드가 average가 int 타입인 경우도 처리해야 함', () {
      // given
      final json = {
        'average': 150, // int 타입
        'highScore': 200,
        'lowScore': 100,
        'gamesPlayed': 10,
      };

      // when
      final stats = ScoreStatistics.fromJson(json);

      // then
      expect(stats.average, 150.0); // double 타입으로 변환되어야 함
      expect(stats.highScore, 200);
      expect(stats.lowScore, 100);
      expect(stats.gamesPlayed, 10);
      expect(stats.additionalStats, null);
    });

    test('fromJson 메서드가 필수 필드가 null인 경우 기본값을 설정해야 함', () {
      // given
      final json = {
        // 필수 필드가 null이거나 누락된 경우
        'average': null,
        'highScore': null,
        'lowScore': null,
        'gamesPlayed': null,
      };

      // when
      final stats = ScoreStatistics.fromJson(json);

      // then
      expect(stats.average, 0.0);
      expect(stats.highScore, 0);
      expect(stats.lowScore, 0);
      expect(stats.gamesPlayed, 0);
      expect(stats.additionalStats, null);
    });

    test('toJson 메서드가 ScoreStatistics 객체를 JSON으로 올바르게 변환해야 함', () {
      // given
      final stats = ScoreStatistics(
        average: 150.5,
        highScore: 200,
        lowScore: 100,
        gamesPlayed: 10,
        additionalStats: {
          'strikes': 5,
          'spares': 3,
        },
      );

      // when
      final json = stats.toJson();

      // then
      expect(json['average'], 150.5);
      expect(json['highScore'], 200);
      expect(json['lowScore'], 100);
      expect(json['gamesPlayed'], 10);
      expect(json['additionalStats']?['strikes'], 5);
      expect(json['additionalStats']?['spares'], 3);
    });
  });
}
