import 'package:block_seasons/game/models/piece.dart';
import 'package:block_seasons/game/models/piece_library.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('PieceLibrary', () {
    test('has a rich fixed-orientation shape set', () {
      expect(PieceLibrary.all.length, greaterThanOrEqualTo(35));
    });

    test('ids are unique', () {
      final ids = PieceLibrary.all.map((p) => p.id).toSet();
      expect(ids.length, PieceLibrary.all.length);
    });

    test('every piece is normalized to its top-left bounding box', () {
      for (final piece in PieceLibrary.all) {
        final minDx =
            piece.offsets.map((o) => o.$1).reduce((a, b) => a < b ? a : b);
        final minDy =
            piece.offsets.map((o) => o.$2).reduce((a, b) => a < b ? a : b);
        expect(minDx, 0, reason: '${piece.id} not normalized in x');
        expect(minDy, 0, reason: '${piece.id} not normalized in y');
      }
    });

    test('offsets are unique and fit in a 5x5 bounding box', () {
      for (final piece in PieceLibrary.all) {
        expect(piece.offsets.toSet().length, piece.offsets.length,
            reason: '${piece.id} has duplicate offsets');
        for (final (dx, dy) in piece.offsets) {
          expect(dx, inInclusiveRange(0, 4), reason: piece.id);
          expect(dy, inInclusiveRange(0, 4), reason: piece.id);
        }
      }
    });

    test('weights are positive and tiers are 1..3', () {
      for (final piece in PieceLibrary.all) {
        expect(piece.weight, greaterThan(0), reason: piece.id);
        expect(piece.tier, inInclusiveRange(1, 3), reason: piece.id);
      }
    });

    test('contains the staple shapes', () {
      for (final id in ['mono', 'square2', 'square3', 'line5_h', 'line5_v']) {
        expect(PieceLibrary.byId(id), isA<Piece>());
      }
    });

    test('byId throws on unknown id', () {
      expect(() => PieceLibrary.byId('nope'), throwsStateError);
    });

    test('small pieces exist for tight late-game boards', () {
      final smalls = PieceLibrary.all.where((p) => p.size <= 2);
      expect(smalls.length, greaterThanOrEqualTo(3));
    });
  });
}
