import 'dart:io';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';

import '../widgets/guide_frame.dart';
import 'card_detector.dart';

/// Quick post-capture gate: guide-crop + ML Kit. No box → ask user to retake.
class CardScanGate {
  /// Returns true when a card-like border is found inside the shooting guide.
  static Future<bool> hasDetectableBorder({
    required String imagePath,
    Size? captureViewport,
    CardDetector? detector,
  }) async {
    final owned = detector == null;
    final det = detector ?? CardDetector();
    try {
      final raw = await File(imagePath).readAsBytes();
      final codec = await ui.instantiateImageCodec(raw);
      final frame = await codec.getNextFrame();
      final fullImage = frame.image;

      final rgba = await fullImage.toByteData(format: ui.ImageByteFormat.rawRgba);
      if (rgba == null) {
        fullImage.dispose();
        return false;
      }

      final fullRaster = img.Image.fromBytes(
        width: fullImage.width,
        height: fullImage.height,
        bytes: rgba.buffer,
        bytesOffset: rgba.offsetInBytes,
        numChannels: 4,
        order: img.ChannelOrder.rgba,
      );
      fullImage.dispose();

      final imageSize = Size(
        fullRaster.width.toDouble(),
        fullRaster.height.toDouble(),
      );
      final guide = captureViewport != null
          ? GuideFrame.inCoverImage(
              viewport: captureViewport,
              imageSize: imageSize,
            )
          : GuideFrame.inImage(imageSize);

      final gx = guide.left.round().clamp(0, fullRaster.width - 1);
      final gy = guide.top.round().clamp(0, fullRaster.height - 1);
      final gw = guide.width.round().clamp(1, fullRaster.width - gx);
      final gh = guide.height.round().clamp(1, fullRaster.height - gy);
      final raster = img.copyCrop(
        fullRaster,
        x: gx,
        y: gy,
        width: gw,
        height: gh,
      );

      final dir = await getTemporaryDirectory();
      final guidePath =
          '${dir.path}/card_gate_${DateTime.now().millisecondsSinceEpoch}.jpg';
      await File(guidePath).writeAsBytes(
        img.encodeJpg(raster, quality: 95),
        flush: true,
      );

      final boxes = await det.detectFile(guidePath);
      final guideSize = Size(
        raster.width.toDouble(),
        raster.height.toDouble(),
      );
      final best = det.pickBest(boxes, imageSize: guideSize);
      return best != null && boxes.isNotEmpty;
    } finally {
      if (owned) {
        await det.dispose();
      }
    }
  }
}
