import 'dart:math';

import 'package:aves/image_providers/full_image_provider.dart';
import 'package:aves/image_providers/region_provider.dart';
import 'package:aves/image_providers/thumbnail_provider.dart';
import 'package:aves/model/entry/cache.dart';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/utils/math_utils.dart';
import 'package:collection/collection.dart';
import 'package:flutter/painting.dart';
import 'package:aves/remote/remote_http.dart';
import 'package:aves/remote/remote_origin.dart';

extension ExtraAvesEntryImages on AvesEntry {
  // === Helper per remoti ===
  bool get isRemote => origin == RemoteOrigin.value;

  bool isThumbnailReady({double extent = 0}) => _isReady(_getThumbnailProviderKey(extent));

  ThumbnailProvider getThumbnail({double extent = 0}) {
    return ThumbnailProvider(_getThumbnailProviderKey(extent));
  }

  ThumbnailProviderKey _getThumbnailProviderKey(double extent) {
    final requestExtent = extent.roundToDouble();
    EntryCache.markThumbnailExtent(requestExtent);
    return ThumbnailProviderKey(
      uri: uri,
      mimeType: mimeType,
      pageId: pageId,
      rotationDegrees: rotationDegrees,
      isFlipped: isFlipped,
      dateModifiedMillis: dateModifiedMillis ?? -1,
      extent: requestExtent,
    );
  }

  RegionProvider getRegion({int sampleSize = 1, double scale = 1, required Rectangle<num> region}) {
    if (isRemote) {
      // Non supportiamo il tiling di region su immagini remote (non c’è file locale).
      throw UnsupportedError("Region tiling not supported for remote images");
    }

    return RegionProvider(
      RegionProviderKey(
        uri: uri,
        mimeType: mimeType,
        pageId: pageId,
        sizeBytes: sizeBytes,
        rotationDegrees: rotationDegrees,
        isFlipped: isFlipped,
        sampleSize: sampleSize,
        regionRect: Rectangle(
          (region.left * scale).round(),
          (region.top * scale).round(),
          (region.width * scale).round(),
          (region.height * scale).round(),
        ),
        imageSize: Size((width * scale).toDouble(), (height * scale).toDouble()),
      ),
    );
  }

  Rectangle<double> get fullImageRegion => Rectangle<double>(.0, .0, width.toDouble(), height.toDouble());

  /// Provider dell’immagine completa.
  /// - Remoto → `NetworkImage` con header Bearer “sincroni” (se già in cache via RemoteHttp.headers()).
  /// - Locale → `FullImage` (pipeline classica Aves).
  ImageProvider get fullImage {
    if (isRemote) {
      final abs = RemoteHttp.absUrl(remotePath ?? path);
      // Se la cache non è ancora popolata, può essere null: chi usa il ramo viewer remoto fa comunque await degli headers.
      final hdrs = RemoteHttp.peekHeaders();
      return NetworkImage(abs, headers: hdrs);
    }

    return FullImage(
      uri: uri,
      mimeType: mimeType,
      pageId: pageId,
      rotationDegrees: rotationDegrees,
      isFlipped: isFlipped,
      isAnimated: isAnimated,
      sizeBytes: sizeBytes,
    );
  }

  bool _isReady(Object providerKey) => imageCache.statusForKey(providerKey).keepAlive;

  List<ThumbnailProvider> get cachedThumbnails =>
      EntryCache.thumbnailRequestExtents.map(_getThumbnailProviderKey).where(_isReady).map(ThumbnailProvider.new).toList();

  ThumbnailProvider get bestCachedThumbnail {
    final sizedThumbnailKey = EntryCache.thumbnailRequestExtents.map(_getThumbnailProviderKey).firstWhereOrNull(_isReady);
    return sizedThumbnailKey != null ? ThumbnailProvider(sizedThumbnailKey) : getThumbnail();
  }

  static int sampleSizeForScale({
    required double magnifierScale,
    required double devicePixelRatio,
  }) {
    var sample = 0;
    if (0 < magnifierScale && magnifierScale < 1) {
      sample = highestPowerOf2(1 / (magnifierScale * devicePixelRatio));
    }
    return max<int>(1, sample);
  }
}
