import 'package:block_seasons/game/engine/auto_player.dart';
import 'package:block_seasons/game/models/stage.dart';
import 'package:flutter_test/flutter_test.dart';

StageConfig _easyClearLines() => StageConfig.fromJson({
      'id': 'bot_easy',
      'seed': 4242,
      'moveLimit': 30,
      'preset': const <Map<String, dynamic>>[],
      'objectives': [
        {'type': 'clearLines', 'count': 1},
      ],
      'stars': {
        'two': {'movesLeft': 10},
        'three': {'movesLeft': 20},
      },
      'generatorProfile': 'mid',
    });

StageConfig _gemStage() => StageConfig.fromJson({
      'id': 'bot_gems',
      'seed': 555,
      'moveLimit': 35,
      'preset': [
        {'x': 1, 'y': 1, 't': 'gem'},
        {'x': 6, 'y': 6, 't': 'gem'},
      ],
      'objectives': [
        {'type': 'clearGems', 'count': 2},
      ],
      'stars': {
        'two': {'movesLeft': 8},
        'three': {'movesLeft': 16},
      },
      'generatorProfile': 'mid',
    });

void main() {
  test('bot terminates and reports a result on every attempt', () {
    for (var attempt = 0; attempt < 10; attempt++) {
      final run = AutoPlayer().play(_easyClearLines(), attempt: attempt);
      expect(run.movesUsed, greaterThan(0));
      expect(run.movesUsed, lessThanOrEqualTo(35));
      if (run.won) {
        expect(run.movesLeft, greaterThanOrEqualTo(0));
        expect(run.stars, inInclusiveRange(1, 3));
      }
    }
  });

  test('bot wins a trivially easy clear-lines stage most of the time', () {
    var wins = 0;
    for (var attempt = 0; attempt < 20; attempt++) {
      if (AutoPlayer().play(_easyClearLines(), attempt: attempt).won) wins++;
    }
    expect(wins, greaterThanOrEqualTo(16), reason: 'bot too weak: $wins/20');
  });

  test('bot pursues gem objectives without dead-ending the board', () {
    var wins = 0;
    for (var attempt = 0; attempt < 20; attempt++) {
      if (AutoPlayer().play(_gemStage(), attempt: attempt).won) wins++;
    }
    expect(wins, greaterThanOrEqualTo(17), reason: 'gem play too weak: $wins/20');
  });

  test('same attempt number reproduces the same run', () {
    final a = AutoPlayer().play(_gemStage(), attempt: 3);
    final b = AutoPlayer().play(_gemStage(), attempt: 3);
    expect(a.won, b.won);
    expect(a.movesUsed, b.movesUsed);
    expect(a.score, b.score);
  });
}
