"""test_lab.py — `pytest -q` (offline; needs numpy + opencv). Success criteria
for the OpenCV preprocessing and the Arabic text logic."""
from __future__ import annotations

import numpy as np

from arabic import (arabic_words_to_number, english_words_to_number,
                    normalize_digits, parse_figure, words_match_figures)
from preprocess import (binarize, deskew, estimate_skew_angle,
                        preprocess_pipeline, to_grayscale)
from synth import CHEQUE_OCR, CHEQUE_OCR_MISMATCH, create_cheque_image


# --- OpenCV preprocessing (real) -------------------------------------------
def test_deskew_straightens_a_crooked_scan():
    skewed = create_cheque_image(angle=8.0)
    before = abs(estimate_skew_angle(to_grayscale(skewed)))
    deskewed, _ = deskew(skewed)
    after = abs(estimate_skew_angle(to_grayscale(deskewed)))
    assert before > 3.0           # it really was skewed
    assert after < before         # deskew reduced it
    assert after < 2.5            # and brought it near straight


def test_binarize_is_binary():
    img = create_cheque_image()
    bw = binarize(to_grayscale(img))
    assert set(np.unique(bw)).issubset({0, 255})


def test_grayscale_drops_channels():
    img = create_cheque_image()
    g = to_grayscale(img)
    assert g.ndim == 2 and img.ndim == 3


def test_pipeline_returns_clean_binary():
    out = preprocess_pipeline(create_cheque_image(angle=5.0))
    assert out.ndim == 2 and set(np.unique(out)).issubset({0, 255})


# --- Arabic numerals & figures ---------------------------------------------
def test_eastern_to_western_numerals():
    assert normalize_digits("٠١٢٣٤٥٦٧٨٩") == "0123456789"
    assert parse_figure("١٬٢٥٠٫٠٠") == 1250.0
    assert parse_figure("1,250.00") == 1250.0


# --- amount-in-words -> number ---------------------------------------------
def test_english_words():
    assert english_words_to_number("one thousand two hundred fifty") == 1250
    assert english_words_to_number("five hundred") == 500
    assert english_words_to_number("three thousand AED only") == 3000


def test_arabic_words():
    assert arabic_words_to_number("ألف ومئتان وخمسون") == 1250
    assert arabic_words_to_number("خمسمئة") == 500
    assert arabic_words_to_number("ثلاثة آلاف") == 3000
    assert arabic_words_to_number("ألفان وخمسمئة") == 2500


# --- the cheque control -----------------------------------------------------
def test_words_match_figures_clean_and_fraud():
    assert words_match_figures(CHEQUE_OCR["amount_words_ar"],
                               CHEQUE_OCR["amount_figures"], lang="ar") is True
    assert words_match_figures(CHEQUE_OCR_MISMATCH["amount_words_ar"],
                               CHEQUE_OCR_MISMATCH["amount_figures"], lang="ar") is False


def test_words_match_figures_english():
    assert words_match_figures("one thousand two hundred fifty", "1,250.00",
                               lang="en") is True
