import 'package:flutter_test/flutter_test.dart';
import 'package:tane/services/ocr/tesseract_label_extractor.dart';

/// Builds one hOCR word span with a bounding box (height = y1 - y0) and an
/// optional recognition confidence.
String word(String text, int x0, int y0, int x1, int y1, {int conf = 90}) =>
    "<span class='ocrx_word' title='bbox $x0 $y0 $x1 $y1; x_wconf $conf'>"
    '$text</span>';

String page(List<String> words) =>
    "<div class='ocr_page'>${words.join('\n')}</div>";

void main() {
  group('pickLabelFromHocr picks the largest print, not the longest line', () {
    test(
      'Aubergine Black Beauty packet → the variety name, not boilerplate',
      () {
        // "Organic Product" (14 letters) is longer than "Black Beauty" (11) but
        // printed smaller — the old longest-line heuristic wrongly picked it.
        final hocr = page([
          word('BonPrime', 120, 300, 300, 335), // brand, tiny
          word('Organic', 130, 1050, 320, 1095), // boilerplate, small
          word('Product', 130, 1100, 340, 1145),
          word('AUBERGINE', 380, 1180, 900, 1300), // the title (tallest)
          word('BLACK', 380, 1330, 620, 1410),
          word('BEAUTY', 640, 1330, 900, 1410),
          word('HERB', 430, 1470, 560, 1510), // boilerplate, small
          word('SEEDS', 580, 1470, 740, 1510),
        ]);
        expect(pickLabelFromHocr(hocr), 'Aubergine Black Beauty');
      },
    );

    test('Cucumber Supermarketer packet → the variety name', () {
      final hocr = page([
        word('BonPrime', 120, 300, 300, 335),
        word('Organic', 130, 1050, 320, 1095),
        word('Product', 130, 1100, 340, 1145),
        word('CUCUMBER', 300, 1200, 820, 1320), // tallest
        word('SUPERMARKETER', 320, 1350, 900, 1430),
        word('HERB', 430, 1470, 560, 1510),
        word('SEEDS', 580, 1470, 740, 1510),
      ]);
      expect(pickLabelFromHocr(hocr), 'Cucumber Supermarketer');
    });

    test('reads left-to-right within the same row', () {
      final hocr = page([
        word('CHERRY', 400, 1000, 560, 1090),
        word('TOMATO', 580, 1000, 760, 1090),
      ]);
      expect(pickLabelFromHocr(hocr), 'Cherry Tomato');
    });

    test('a page of only boilerplate yields null', () {
      final hocr = page([
        word('Organic', 130, 1050, 320, 1095),
        word('Product', 130, 1100, 340, 1145),
        word('HERB', 430, 1470, 560, 1510),
        word('SEEDS', 580, 1470, 740, 1510),
      ]);
      expect(pickLabelFromHocr(hocr), isNull);
    });

    test('empty hOCR yields null', () {
      expect(pickLabelFromHocr(page(const [])), isNull);
      expect(pickLabelFromHocr(''), isNull);
    });

    test('short OCR fragments ("Re Ma") are dropped → no suggestion', () {
      // Blurry misread into 1–2 char blobs: better nothing than "Re Ma".
      final hocr = page([
        word('Re', 300, 1200, 420, 1320, conf: 40),
        word('Ma', 460, 1200, 600, 1320, conf: 40),
      ]);
      expect(pickLabelFromHocr(hocr), isNull);
    });

    test('a plausibly-misread title word is kept (user edits it)', () {
      // "Sucumber" (C read as S) is useful as an editable prefill.
      final hocr = page([
        word('Sucumber', 300, 1200, 820, 1320, conf: 45),
        word('Organic', 130, 1050, 320, 1095, conf: 80),
      ]);
      expect(pickLabelFromHocr(hocr), 'Sucumber');
    });

    test('a near-zero confidence word is dropped by the floor', () {
      final hocr = page([word('Xzqwp', 300, 1200, 820, 1320, conf: 8)]);
      expect(pickLabelFromHocr(hocr), isNull);
    });
  });
}
