import re
import sys
from typing import List
from pathlib import Path

# 添加 ocr_platform 根目录到 Python 路径（用于导入 ocr_utils）
# 使用 resolve() 确保路径是绝对路径，避免相对路径导致的 IndexError
_file_path = Path(__file__).resolve()
ocr_platform_root = _file_path.parents[1]  # data_type_detector.py -> ocr_comparator -> ocr_platform
if str(ocr_platform_root) not in sys.path:
    sys.path.insert(0, str(ocr_platform_root))

# 从 ocr_utils 导入数字解析函数
from ocr_utils.number_utils import parse_number, normalize_text_number


class DataTypeDetector:
    """数据类型检测和解析"""
    
    @staticmethod
    def is_numeric(text: str) -> bool:
        """判断文本是否为数字（15位以内的数值）"""
        if not text:
            return False
        
        clean_text = re.sub(r'[,，\s-]', '', text)
        
        if len(clean_text) > 15:
            return False
        
        try:
            float(clean_text)
            return True
        except ValueError:
            return False
    
    @staticmethod
    def is_text_number(text: str) -> bool:
        """判断是否为文本型数字（如账号、订单号）"""
        if not text:
            return False
        
        clean_text = re.sub(r'[\s-]', '', text)
        
        # 排除日期格式 yyyymmdd
        if len(clean_text) == 8 and clean_text.isdigit():
            # 检查是否为合法日期
            try:
                year = int(clean_text[:4])
                month = int(clean_text[4:6])
                day = int(clean_text[6:8])
                if 1900 <= year <= 2100 and 1 <= month <= 12 and 1 <= day <= 31:
                    return False  # 这是日期，不是文本型数字
            except ValueError:
                pass
        
        if clean_text.isdigit() and len(clean_text) > 15:
            return True
        
        if re.match(r'^[\d\s-]+$', text) and len(clean_text) > 10:
            return True
        
        return False
    
    @staticmethod
    def is_datetime(text: str) -> bool:
        """判断文本是否为日期时间格式"""
        if not text:
            return False
        
        datetime_patterns = [
            r'\d{4}[-/]\d{1,2}[-/]\d{1,2}',
            r'\d{4}[-/]\d{1,2}[-/]\d{1,2}\s*\d{1,2}:\d{1,2}:\d{1,2}',
            r'\d{4}年\d{1,2}月\d{1,2}日',
            r'^\d{8}$',  # yyyymmdd 格式
        ]
        
        for pattern in datetime_patterns:
            if re.search(pattern, str(text).strip()):
                # 对于 yyyymmdd 格式，验证日期合法性
                if pattern == r'^\d{8}$':
                    try:
                        clean_text = str(text).strip()
                        year = int(clean_text[:4])
                        month = int(clean_text[4:6])
                        day = int(clean_text[6:8])
                        if 1900 <= year <= 2100 and 1 <= month <= 12 and 1 <= day <= 31:
                            return True
                    except (ValueError, IndexError):
                        continue
                else:
                    return True
        
        return False
    
    @staticmethod
    def parse_number(text: str) -> float:
        """
        解析数字，处理千分位和货币符号
        
        此方法是对 ocr_utils.number_utils.parse_number 的包装，保持向后兼容性。
        """
        return parse_number(text)
    
    @staticmethod
    def extract_datetime(text: str) -> str:
        """提取并标准化日期时间"""
        patterns = [
            # yyyy-mm-dd hh:mm:ss
            (r'(\d{4})[-/](\d{1,2})[-/](\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})', 
             lambda m: f"{m.group(1)}-{m.group(2).zfill(2)}-{m.group(3).zfill(2)} {m.group(4).zfill(2)}:{m.group(5).zfill(2)}:{m.group(6).zfill(2)}"),
            # yyyy-mm-dd
            (r'(\d{4})[-/](\d{1,2})[-/](\d{1,2})', 
             lambda m: f"{m.group(1)}-{m.group(2).zfill(2)}-{m.group(3).zfill(2)}"),
            # yyyy年mm月dd日
            (r'(\d{4})年(\d{1,2})月(\d{1,2})日', 
             lambda m: f"{m.group(1)}-{m.group(2).zfill(2)}-{m.group(3).zfill(2)}"),
            # yyyymmdd
            (r'^(\d{4})(\d{2})(\d{2})$',
             lambda m: f"{m.group(1)}{m.group(2)}{m.group(3)}"),
        ]
        
        for pattern, formatter in patterns:
            match = re.search(pattern, str(text).strip())
            if match:
                if pattern == r'^(\d{4})(\d{2})(\d{2})$':
                    # 验证日期合法性
                    try:
                        year = int(match.group(1))
                        month = int(match.group(2))
                        day = int(match.group(3))
                        if not (1900 <= year <= 2100 and 1 <= month <= 12 and 1 <= day <= 31):
                            continue
                    except ValueError:
                        continue
                return formatter(match)
        
        return text
    
    @staticmethod
    def detect_column_type(column_values: List[str]) -> str:
        """检测列的数据类型"""
        if not column_values:
            return 'text'
        
        non_empty_values = [v for v in column_values if v and v.strip() and v not in ['/', '-']]
        if not non_empty_values:
            return 'text'
        
        # 先检测日期时间（优先级最高，避免 yyyymmdd 被误判为文本型数字）
        datetime_count = sum(1 for v in non_empty_values[:5] if DataTypeDetector.is_datetime(v))
        if datetime_count >= len(non_empty_values[:5]) * 0.6:
            return 'datetime'
        
        # 检测文本型数字
        text_number_count = sum(1 for v in non_empty_values[:5] if DataTypeDetector.is_text_number(v))
        if text_number_count >= len(non_empty_values[:5]) * 0.6:
            return 'text'
        
        # 检测数字
        numeric_count = sum(1 for v in non_empty_values[:5] 
                           if DataTypeDetector.is_numeric(v) and not DataTypeDetector.is_text_number(v))
        
        if numeric_count >= len(non_empty_values[:5]) * 0.6:
            return 'numeric'
        
        return 'text'
    
    @staticmethod
    def normalize_text_number(text: str) -> str:
        """
        标准化文本型数字：移除空格和连字符
        
        此方法是对 ocr_utils.number_utils.normalize_text_number 的包装，保持向后兼容性。
        """
        return normalize_text_number(text)