"""
编辑器业务逻辑服务
"""

import base64
import json
import io
from pathlib import Path
from typing import Dict, Tuple, Optional, Any, cast
from PIL import Image
from loguru import logger

import sys
from pathlib import Path

# 添加 ocr_platform 根目录到 Python 路径（用于导入 core 和 ocr_utils）
_file_path = Path(__file__).resolve()
ocr_platform_root = _file_path.parents[2]  # editor_service.py -> services -> backend -> table_line_generator -> ocr_platform
if str(ocr_platform_root) not in sys.path:
    sys.path.insert(0, str(ocr_platform_root))

from table_line_generator.core.ocr_parser import OcrParser
from table_line_generator.core.table_analyzer import TableAnalyzer
from table_line_generator.core.drawing_service import DrawingService


class EditorService:
    """编辑器服务"""
    
    MAX_IMAGE_SIZE = 4096
    
    @staticmethod
    def _extract_suggested_filename(json_path: str) -> str:
        """
        从 JSON 文件路径中提取建议的文件名（不含.json后缀）
        
        例如: "/path/to/施博深_page_001.json" -> "施博深_page_001"
        
        Args:
            json_path: JSON 文件的完整路径
            
        Returns:
            提取的文件名（不含扩展名）
        """
        path = Path(json_path)
        return path.stem
    
    @classmethod
    def process_upload(
        cls,
        json_content: bytes,
        image_content: bytes,
        json_path: Optional[str] = None,
        annotated_structure: Optional[Dict] = None
    ) -> Dict[str, Any]:
        """
        处理上传的文件
        
        Args:
            json_content: JSON 文件内容
            image_content: 图片文件内容
            json_path: JSON 文件路径（用于提取建议文件名）
            annotated_structure: 标注结果（如果提供，直接使用）
            
        Returns:
            处理结果
        """
        # 解析 JSON
        try:
            ocr_result = json.loads(json_content.decode('utf-8'))
        except json.JSONDecodeError as e:
            raise ValueError(f"JSON 解析失败: {e}")
        
        # 加载图片
        try:
            image = Image.open(io.BytesIO(image_content))
            if image.mode != 'RGB':
                image = image.convert('RGB')
        except Exception as e:
            raise ValueError(f"图片加载失败: {e}")
        
        original_size = image.size
        
        # 检查并缩放图片
        image, scale_factor = TableAnalyzer.resize_image_if_needed(
            image, cls.MAX_IMAGE_SIZE
        )
        
        if scale_factor < 1.0:
            logger.info(f"图片已缩放: {original_size} -> {image.size}, scale={scale_factor:.3f}")
        
        # 解析 OCR 数据
        try:
            table_bbox, ocr_data = OcrParser.parse(ocr_result)
        except Exception as e:
            raise ValueError(f"OCR 数据解析失败: {e}")
        
        # ✅ 如果提供了标注结果，直接使用
        if annotated_structure:
            logger.info("使用保存的标注结果")
            structure = annotated_structure
        else:
            # 分析表格结构
            analyzer = TableAnalyzer(image, ocr_data)
            structure = analyzer.analyze()
        
        # 图片转 base64
        image_base64 = cls._image_to_base64(image)
        
        result = {
            'image_base64': image_base64,
            'structure': structure,
            'image_size': {
                'width': image.size[0],
                'height': image.size[1]
            },
            'scale_factor': scale_factor,
            'ocr_data': ocr_data
        }
        
        # 如果提供了 json_path，提取建议的文件名
        if json_path:
            result['suggested_filename'] = cls._extract_suggested_filename(json_path)
        
        return result

    @classmethod
    def analyze_structure(
        cls,
        ocr_data: Dict,
        params: Dict
    ) -> Dict:
        """
        重新分析表格结构
        
        Args:
            ocr_data: OCR 数据
            params: 分析参数
            
        Returns:
            表格结构
        """
        structure = TableAnalyzer.analyze_structure_only(
            ocr_data,
            y_tolerance=params.get('y_tolerance', 5),
            x_tolerance=params.get('x_tolerance', 10),
            min_row_height=params.get('min_row_height', 20),
            method=params.get('method', 'auto')
        )
        return structure

    @classmethod
    def save_result(
        cls,
        structure: Dict,
        image_base64: Optional[str] = None,
        output_dir: str = './output',
        filename: str = 'structure',
        image_filename: Optional[str] = None,
        overwrite_mode: str = 'overwrite',
        structure_suffix: str = '_structure',
        image_suffix: str = '',
        line_width: int = 2,
        line_color: Tuple[int, int, int] = (0, 0, 0)
    ) -> Dict[str, Optional[str]]:
        """
        保存结果
        
        Args:
            structure: 表格结构
            image_base64: Base64 编码的图片（可选）
            output_dir: 输出目录
            filename: 结构文件名（不含扩展名）
            image_filename: 图片文件名（不含扩展名）
            overwrite_mode: 覆盖策略 (overwrite/skip/new)
            structure_suffix: 结构文件后缀（默认 '_structure'）
            image_suffix: 图片文件后缀（默认 ''）
            line_width: 线条宽度
            line_color: 线条颜色
            
        Returns:
            保存的文件路径字典
        """
        from datetime import datetime
        
        output_path = Path(output_dir)
        output_path.mkdir(parents=True, exist_ok=True)
        
        # 保存结构 JSON
        # 确保 structure_suffix 以 .json 结尾
        if not structure_suffix.endswith('.json'):
            structure_suffix = structure_suffix + '.json'
        structure_path = output_path / f"{filename}{structure_suffix}"
        
        # 处理覆盖策略
        if structure_path.exists() and overwrite_mode != 'overwrite':
            if overwrite_mode == 'skip':
                logger.info(f"文件已存在，跳过保存: {structure_path}")
                return {
                    'structure_path': str(structure_path),
                    'image_path': None
                }
            elif overwrite_mode == 'new':
                # 添加时间戳生成新文件名
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                base_suffix = structure_suffix.replace('.json', '')
                structure_path = output_path / f"{filename}_{timestamp}{base_suffix}.json"
        
        # 确保 modified_h_lines 和 modified_v_lines 是列表
        structure_to_save = dict(structure)
        if 'modified_h_lines' in structure_to_save:
            structure_to_save['modified_h_lines'] = list(structure_to_save['modified_h_lines'])
        if 'modified_v_lines' in structure_to_save:
            structure_to_save['modified_v_lines'] = list(structure_to_save['modified_v_lines'])
        
        # 移除不需要保存的字段
        for key in ['rows', 'columns']:
            structure_to_save.pop(key, None)
        
        with open(structure_path, 'w', encoding='utf-8') as f:
            json.dump(structure_to_save, f, ensure_ascii=False, indent=2)
        
        logger.info(f"保存结构文件: {structure_path}")
        
        # 保存图片（可选）
        image_path = None
        if image_base64:
            if image_filename is None:
                image_filename = filename
            
            # 确保 image_suffix 以 .png 结尾
            if not image_suffix.endswith('.png'):
                image_suffix = image_suffix + '.png'
            image_path = output_path / f"{image_filename}{image_suffix}"
            
            # 处理覆盖策略
            if image_path.exists() and overwrite_mode == 'new':
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                base_suffix = image_suffix.replace('.png', '')
                image_path = output_path / f"{image_filename}_{timestamp}{base_suffix}.png"
            
            # 解码图片并绘制表格线
            image = cls._base64_to_image(image_base64)
            image_with_lines = DrawingService.draw_clean_lines(
                image, structure, line_width=line_width, line_color=cast(Tuple[int, int, int], line_color)
            )
            
            image_with_lines.save(str(image_path), 'PNG')
            logger.info(f"保存图片文件: {image_path}")
        
        return {
            'structure_path': str(structure_path),
            'image_path': str(image_path) if image_path else None
        }

    @staticmethod
    def _image_to_base64(image: Image.Image) -> str:
        """将 PIL Image 转换为 base64 字符串"""
        buffer = io.BytesIO()
        image.save(buffer, format='PNG')
        return base64.b64encode(buffer.getvalue()).decode('utf-8')

    @staticmethod
    def _base64_to_image(base64_str: str) -> Image.Image:
        """将 base64 字符串转换为 PIL Image"""
        # 处理可能的 data URL 前缀
        if ',' in base64_str:
            base64_str = base64_str.split(',')[1]
        
        image_data = base64.b64decode(base64_str)
        return Image.open(io.BytesIO(image_data))
