"""
VYNDR Image-to-Grade OCR
Accept bet slip screenshot → preprocess → OCR → parse → fuzzy match → grade.
"""

import logging
import io
from flask import Blueprint, request, jsonify

logger = logging.getLogger('vyndr')
image_grade_bp = Blueprint('image_grade', __name__)


def preprocess_image(image_bytes):
    """
    Preprocess image for OCR: grayscale, contrast enhancement, threshold.

    Args:
        image_bytes: Raw image bytes.

    Returns:
        PIL Image ready for OCR.
    """
    try:
        from PIL import Image, ImageEnhance, ImageFilter
        img = Image.open(io.BytesIO(image_bytes))
        img = img.convert('L')  # grayscale
        enhancer = ImageEnhance.Contrast(img)
        img = enhancer.enhance(2.0)
        img = img.filter(ImageFilter.SHARPEN)
        return img
    except ImportError:
        logger.error('[VYNDR] Pillow not installed')
        return None


def ocr_image(image):
    """
    Run OCR on preprocessed image.

    Args:
        image: PIL Image.

    Returns:
        Dict with text and confidence.
    """
    try:
        import pytesseract
        text = pytesseract.image_to_string(image)
        data = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)
        confidences = [int(c) for c in data['conf'] if int(c) > 0]
        avg_conf = sum(confidences) / len(confidences) if confidences else 0
        return {'text': text.strip(), 'confidence': round(avg_conf, 1)}
    except ImportError:
        logger.error('[VYNDR] pytesseract not installed')
        return {'text': '', 'confidence': 0}
    except Exception as e:
        logger.error(f'[VYNDR] OCR failed: {e}')
        return {'text': '', 'confidence': 0}


def parse_bet_slip(text):
    """
    Parse OCR text to extract bet slip components.

    Args:
        text: OCR extracted text.

    Returns:
        List of parsed leg dicts with player, stat_type, line, over_under.
    """
    legs = []
    lines = text.split('\n')

    stat_keywords = {
        'pts': 'points', 'points': 'points', 'reb': 'rebounds',
        'rebounds': 'rebounds', 'ast': 'assists', 'assists': 'assists',
        'threes': 'threes', '3pt': 'threes', '3-pointers': 'threes',
        'strikeouts': 'strikeouts', 'ks': 'strikeouts', 'k\'s': 'strikeouts',
        'hits': 'hits', 'total bases': 'total_bases', 'tb': 'total_bases',
        'rbi': 'rbi', 'home runs': 'home_runs', 'hr': 'home_runs',
        'walks': 'walks', 'bb': 'walks'
    }

    for line in lines:
        line_lower = line.lower().strip()
        if not line_lower:
            continue

        # Try to find over/under
        over_under = None
        if 'over' in line_lower:
            over_under = 'over'
        elif 'under' in line_lower:
            over_under = 'under'

        # Try to find stat type
        stat_type = None
        for keyword, mapped in stat_keywords.items():
            if keyword in line_lower:
                stat_type = mapped
                break

        # Try to find line value (number with optional .5)
        import re
        numbers = re.findall(r'\d+\.?\d*', line)
        prop_line = None
        for n in numbers:
            val = float(n)
            if 0.5 <= val <= 99.5:
                prop_line = val
                break

        if stat_type and prop_line and over_under:
            # Player name is whatever text precedes the stat keyword
            legs.append({
                'raw_text': line.strip(),
                'stat_type': stat_type,
                'line': prop_line,
                'over_under': over_under,
                'player_name': None  # needs fuzzy matching
            })

    return legs


@image_grade_bp.route('/from-image', methods=['POST'])
def grade_from_image():
    """
    Accept bet slip screenshot, OCR it, parse legs, and grade.

    Request: multipart/form-data with 'image' file.

    Returns:
        JSON with parsed legs, OCR confidence, and grades (or confirmation request).
    """
    if 'image' not in request.files:
        return jsonify({'error': 'No image file provided'}), 400

    image_file = request.files['image']
    image_bytes = image_file.read()

    if len(image_bytes) == 0:
        return jsonify({'error': 'Empty image file'}), 400

    # Preprocess
    processed = preprocess_image(image_bytes)
    if processed is None:
        return jsonify({'error': 'Image processing failed'}), 500

    # OCR
    ocr_result = ocr_image(processed)

    # Parse
    legs = parse_bet_slip(ocr_result['text'])

    # Low confidence — ask user to confirm
    if ocr_result['confidence'] < 60:
        return jsonify({
            'status': 'low_confidence',
            'ocr_confidence': ocr_result['confidence'],
            'extracted_text': ocr_result['text'],
            'parsed_legs': legs,
            'message': 'OCR confidence is low. Please confirm the extracted information.'
        })

    return jsonify({
        'status': 'parsed',
        'ocr_confidence': ocr_result['confidence'],
        'legs': legs,
        'leg_count': len(legs),
        'note': 'Legs parsed. Submit to /api/mlb/grade or /api/nba/grade for grading.'
    })
