import 'dart:ui' as ui;

import 'package:dio/dio.dart';
import 'package:flame/components.dart';
import 'package:flutter/foundation.dart';

import '../config.dart';

/// بارگذاریِ تصاویرِ کارت از backend (نه bundle داخل اپ) تا حجم اپ کم بماند.
/// هر اسکین یک پوشه روی سرور دارد: `/cards/<skin>/<code>.png` و `/cards/<skin>/back.jpg`.
/// تصاویرِ دانلودشده در حافظه کش می‌شوند تا هر کارت فقط یک‌بار از شبکه بیاید.
class CardImages {
  CardImages._();

  static const _fallbackSkin = 'simple';
  static final Dio _dio = Dio(BaseOptions(
    responseType: ResponseType.bytes,
    connectTimeout: const Duration(seconds: 10),
    receiveTimeout: const Duration(seconds: 12),
    validateStatus: (s) => s != null && s >= 200 && s < 300,
  ));
  static final Map<String, Future<Sprite?>> _cache = {};

  static String _url(String skin, String file) =>
      '${AppConfig.baseUrl}/cards/$skin/$file';

  /// اسپرایتِ رویِ یک کارت (مثل "AS"). در صورت خطا/۴۰۴ به اسکینِ پیش‌فرض و
  /// سپس به `null` (کشیدنِ برداری در CardComponent) برمی‌گردد.
  static Future<Sprite?> front(String skin, String code) =>
      _load(skin, '$code.png');

  /// اسپرایتِ پشتِ کارت برای اسکین داده‌شده.
  static Future<Sprite?> back(String skin) => _load(skin, 'back.jpg');

  static Future<Sprite?> _load(String skin, String file) {
    final key = '$skin/$file';
    return _cache.putIfAbsent(key, () => _fetch(skin, file));
  }

  static Future<Sprite?> _fetch(String skin, String file) async {
    final sprite = await _fetchFrom(skin, file);
    if (sprite != null) return sprite;
    if (skin != _fallbackSkin) return _fetchFrom(_fallbackSkin, file);
    return null;
  }

  static Future<Sprite?> _fetchFrom(String skin, String file) async {
    try {
      final res = await _dio.get<List<int>>(_url(skin, file));
      final data = res.data;
      if (data == null || data.isEmpty) return null;
      final image = await _decode(Uint8List.fromList(data));
      return Sprite(image);
    } catch (e) {
      debugPrint('CardImages: $skin/$file failed: $e');
      return null;
    }
  }

  static Future<ui.Image> _decode(Uint8List bytes) async {
    final codec = await ui.instantiateImageCodec(bytes);
    final frame = await codec.getNextFrame();
    return frame.image;
  }
}
