import 'dart:math';

import 'types.dart';

final Random _random = Random();

List<T> shuffleList<T>(List<T> arr) {
  final a = List<T>.from(arr);
  for (int i = a.length - 1; i > 0; i--) {
    final int j = _random.nextInt(i + 1);
    final T temp = a[i];
    a[i] = a[j];
    a[j] = temp;
  }
  return a;
}

List<CardModel> createDeck({
  required int rows,
  required int totalCards,
  required int poolSize,
  required List<String> allFaceIds,
}) {
  if (totalCards <= 0) {
    throw Exception('totalCards must be > 0');
  }
  if (totalCards.isOdd) {
    throw Exception('totalCards must be even');
  }
  if (allFaceIds.isEmpty) {
    throw Exception('allFaceIds must not be empty');
  }

  final pairs = totalCards ~/ 2;
  final actualPoolSize = poolSize.clamp(1, allFaceIds.length);
  final pool = shuffleList(allFaceIds).take(actualPoolSize).toList();

  if (pool.isEmpty) {
    throw Exception('pool must not be empty');
  }

  final List<String> picked = [];
  if (pool.length >= pairs) {
    picked.addAll(shuffleList(pool).take(pairs));
  } else {
    picked.addAll(pool);
    final remain = pairs - pool.length;
    for (int i = 0; i < remain; i++) {
      picked.add(pool[_random.nextInt(pool.length)]);
    }
  }

  final doubled = picked.expand((e) => [e, e]).toList();
  final shuffled = shuffleList(doubled);

  return shuffled.asMap().entries.map((entry) {
    final idx = entry.key;
    final faceId = entry.value;
    return CardModel(
      id: '$faceId-$idx-${_random.nextInt(1 << 32).toRadixString(16)}',
      faceId: faceId,
      isFlipped: false,
      isMatched: false,
    );
  }).toList();
}
