"""
并行处理模块

支持多个香菇的并行分析，进一步提升性能
"""

import cv2
import numpy as np
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Dict, List
import logging

try:
    from .mushroom_detector import MushroomDetector, MushroomSegmenter
    from .diameter_calculator import DiameterCalculator
    from .crack_analyzer import CrackRatioAnalyzer
except ImportError:  # pragma: no cover - fallback for direct script usage
    from mushroom_detector import MushroomDetector, MushroomSegmenter
    from diameter_calculator import DiameterCalculator
    from crack_analyzer import CrackRatioAnalyzer


def process_single_mushroom_roi(
    mushroom_id: int,
    box: List[float],
    image: np.ndarray,
    detector: MushroomDetector,
    segmenter: MushroomSegmenter,
    diameter_calc: DiameterCalculator,
    crack_analyzer: CrackRatioAnalyzer,
    px_per_mm: float,
    confidence: float
) -> Dict:
    """
    处理单个香菇ROI（独立函数，可并行执行）

    这是ROI并行处理哲学的核心：
    - 每个香菇ROI完全独立
    - 可以在不同线程/进程中并行处理
    - 互不干扰，无需同步

    参数:
        mushroom_id: 香菇ID
        box: 检测框
        image: 原始图像（只读）
        detector, segmenter, diameter_calc, crack_analyzer: 各模块实例
        px_per_mm: 像素/毫米比例
        confidence: 检测置信度

    返回:
        单个香菇的分析结果
    """
    result = {
        'mushroom_id': mushroom_id,
        'detection_confidence': confidence
    }

    try:
        # Step 1: 裁剪ROI
        roi_image, offset = detector.crop_roi(image, box, padding_ratio=0.1)

        logging.info(f"香菇 {mushroom_id}: ROI尺寸 {roi_image.shape[:2]}")

        # Step 2: SAM分割
        cap_mask_roi = segmenter.segment_roi(roi_image, box, offset)

        if cap_mask_roi is None:
            result['error'] = '分割失败'
            return result

        # Step 3: 计算直径
        diameter_result = diameter_calc.calculate(cap_mask_roi, px_per_mm)

        if diameter_result is None:
            result['error'] = '直径计算失败'
            return result

        result['diameter_px'] = diameter_result['diameter_px']
        result['diameter_mm'] = diameter_result['diameter_mm']
        result['cap_area_px'] = diameter_result['cap_area_px']
        result['cap_area_mm2'] = diameter_result['cap_area_mm2']

        # Step 4: 计算开裂比
        crack_result = crack_analyzer.extract_crack_pattern(roi_image, cap_mask_roi)

        result['crack_ratio'] = crack_result['crack_ratio']
        result['crack_ratio_percent'] = crack_result['crack_ratio_percent']
        result['crack_area_px'] = crack_result['crack_area_px']
        result['grade'] = crack_result['grade']
        result['v_threshold'] = crack_result['v_threshold']
        result['s_threshold'] = crack_result['s_threshold']

        # 保存可视化数据
        result['_box'] = box
        result['_offset'] = offset
        result['_cap_mask_roi'] = cap_mask_roi
        result['_crack_mask_roi'] = crack_result['crack_mask']

        pt1_roi = diameter_result['point1']
        pt2_roi = diameter_result['point2']
        result['_diameter_pt1'] = (pt1_roi[0] + offset[0], pt1_roi[1] + offset[1])
        result['_diameter_pt2'] = (pt2_roi[0] + offset[0], pt2_roi[1] + offset[1])

        logging.info(
            f"香菇 {mushroom_id} 完成 - "
            f"直径: {result['diameter_mm']:.2f}mm, "
            f"开裂比: {result['crack_ratio_percent']:.2f}%"
        )

    except Exception as e:
        logging.error(f"香菇 {mushroom_id} 处理失败: {str(e)}")
        result['error'] = str(e)

    return result


def process_mushrooms_parallel(
    detections: List[Dict],
    image: np.ndarray,
    detector: MushroomDetector,
    segmenter: MushroomSegmenter,
    diameter_calc: DiameterCalculator,
    crack_analyzer: CrackRatioAnalyzer,
    px_per_mm: float,
    max_workers: int = 4
) -> List[Dict]:
    """
    并行处理多个香菇

    性能对比：
    - 单线程：香菇1(1s) + 香菇2(1s) + 香菇3(1s) = 3秒
    - 并行(3线程)：max(香菇1, 香菇2, 香菇3) ≈ 1秒

    参数:
        detections: YOLO检测结果列表
        image: 原始图像
        detector等: 各模块实例
        px_per_mm: 像素/毫米比例
        max_workers: 最大并行线程数

    返回:
        所有香菇的分析结果列表（保持原始顺序）
    """
    logging.info(f"开始并行处理 {len(detections)} 个香菇（{max_workers}线程）")

    # 创建线程池
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交所有任务
        futures = {}
        for idx, detection in enumerate(detections):
            future = executor.submit(
                process_single_mushroom_roi,
                mushroom_id=idx,
                box=detection['box'],
                image=image,
                detector=detector,
                segmenter=segmenter,
                diameter_calc=diameter_calc,
                crack_analyzer=crack_analyzer,
                px_per_mm=px_per_mm,
                confidence=detection['confidence']
            )
            futures[future] = idx

        # 收集结果（保持顺序）
        results = [None] * len(detections)
        for future in as_completed(futures):
            idx = futures[future]
            try:
                result = future.result()
                results[idx] = result
            except Exception as e:
                logging.error(f"任务 {idx} 异常: {str(e)}")
                results[idx] = {
                    'mushroom_id': idx,
                    'error': str(e)
                }

    logging.info("并行处理完成")
    return results


if __name__ == "__main__":
    # 这个模块主要作为库使用，不直接运行
    print("并行处理模块 - 导入到integrated_analyzer中使用")
