"""
单位转换处理程序
-------------
处理不同单位的转换逻辑
"""

import logging
from typing import Dict, Optional, Any, Tuple, Protocol
from abc import ABC, abstractmethod

from app.core.utils.log_utils import get_logger

logger = get_logger(__name__)


class UnitHandler(ABC):
    """
    单位处理器基类：定义单位处理接口
    """
    
    @abstractmethod
    def can_handle(self, product: Dict[str, Any]) -> bool:
        """
        检查是否可以处理该商品
        
        Args:
            product: 商品信息字典
            
        Returns:
            是否可以处理
        """
        pass
    
    @abstractmethod
    def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
        """
        处理单位转换
        
        Args:
            product: 商品信息字典
            level1: 一级包装数量
            level2: 二级包装数量
            level3: 三级包装数量，可能为None
            
        Returns:
            处理后的商品信息字典
        """
        pass


class JianUnitHandler(UnitHandler):
    """
    处理"件"单位的转换
    """
    
    def can_handle(self, product: Dict[str, Any]) -> bool:
        """
        检查是否可以处理该商品（单位为"件"）
        
        Args:
            product: 商品信息字典
            
        Returns:
            是否可以处理
        """
        unit = str(product.get('unit', '')).strip()
        # 匹配"件"、"件、"、"件装"等
        return unit == '件' or unit.startswith('件')
    
    def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
        """
        处理"件"单位转换：数量×包装数量，单价÷包装数量，单位转为"瓶"
        
        Args:
            product: 商品信息字典
            level1: 一级包装数量
            level2: 二级包装数量
            level3: 三级包装数量，可能为None
            
        Returns:
            处理后的商品信息字典
        """
        result = product.copy()
        
        quantity = result.get('quantity', 0)
        price = result.get('price', 0)
        
        # 计算包装数量（二级*三级，如果无三级则仅二级）
        packaging_count = level2 * (level3 or 1)
        
        # 数量×包装数量
        new_quantity = quantity * packaging_count
        
        # 单价÷包装数量
        new_price = price / packaging_count if price else 0
        
        logger.info(f"件单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 件 -> 瓶")
        
        result['quantity'] = new_quantity
        result['price'] = new_price
        result['unit'] = '瓶'
        
        return result


class BoxUnitHandler(UnitHandler):
    """
    处理"箱"单位的转换
    """
    
    def can_handle(self, product: Dict[str, Any]) -> bool:
        """
        检查是否可以处理该商品（单位为"箱"）
        
        Args:
            product: 商品信息字典
            
        Returns:
            是否可以处理
        """
        unit = str(product.get('unit', '')).strip()
        # 匹配"箱"、"箱、"、"箱装"等
        return unit == '箱' or unit.startswith('箱')
    
    def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
        """
        处理"箱"单位转换：数量×包装数量，单价÷包装数量，单位转为"瓶"
        
        Args:
            product: 商品信息字典
            level1: 一级包装数量
            level2: 二级包装数量
            level3: 三级包装数量，可能为None
            
        Returns:
            处理后的商品信息字典
        """
        result = product.copy()
        
        quantity = result.get('quantity', 0)
        price = result.get('price', 0)
        
        # 计算包装数量（二级*三级，如果无三级则仅二级）
        packaging_count = level2 * (level3 or 1)
        
        # 数量×包装数量
        new_quantity = quantity * packaging_count
        
        # 单价÷包装数量
        new_price = price / packaging_count if price else 0
        
        logger.info(f"箱单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 箱 -> 瓶")
        
        result['quantity'] = new_quantity
        result['price'] = new_price
        result['unit'] = '瓶'
        
        return result


class TiHeUnitHandler(UnitHandler):
    """
    处理"提"和"盒"单位的转换
    """
    
    def can_handle(self, product: Dict[str, Any]) -> bool:
        """
        检查是否可以处理该商品（单位为"提"或"盒"）
        
        Args:
            product: 商品信息字典
            
        Returns:
            是否可以处理
        """
        unit = str(product.get('unit', '')).strip()
        return unit in ['提', '盒'] or unit.startswith('提') or unit.startswith('盒')
    
    def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
        """
        处理"提"和"盒"单位转换：
        - 如果是三级规格，按件处理（数量×包装数量，单价÷包装数量，单位转为"瓶"）
        - 如果是二级规格，保持不变
        
        Args:
            product: 商品信息字典
            level1: 一级包装数量
            level2: 二级包装数量
            level3: 三级包装数量，可能为None
            
        Returns:
            处理后的商品信息字典
        """
        result = product.copy()
        
        quantity = result.get('quantity', 0)
        price = result.get('price', 0)
        unit = result.get('unit', '')
        
        # 如果是三级规格，按件处理
        if level3 is not None:
            # 计算包装数量 - 只乘以最后一级数量
            packaging_count = level3
            
            # 数量×包装数量
            new_quantity = quantity * packaging_count
            
            # 单价÷包装数量
            new_price = price / packaging_count if price else 0
            
            logger.info(f"提/盒单位(三级规格)处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: {unit} -> 瓶")
            
            result['quantity'] = new_quantity
            result['price'] = new_price
            result['unit'] = '瓶'
        else:
            # 如果是二级规格，保持不变
            logger.info(f"提/盒单位(二级规格)处理: 保持原样 数量: {quantity}, 单价: {price}, 单位: {unit}")
        
        return result


class GiftUnitHandler(UnitHandler):
    """
    处理赠品的特殊情况
    """
    
    def can_handle(self, product: Dict[str, Any]) -> bool:
        """
        检查是否可以处理该商品（是否为赠品）
        
        Args:
            product: 商品信息字典
            
        Returns:
            是否可以处理
        """
        return product.get('is_gift', False) is True
    
    def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
        """
        处理赠品的单位转换：
        - 对于件/箱单位，数量仍然需要转换，但赠品的单价保持为0
        
        Args:
            product: 商品信息字典
            level1: 一级包装数量
            level2: 二级包装数量
            level3: 三级包装数量，可能为None
            
        Returns:
            处理后的商品信息字典
        """
        result = product.copy()
        
        unit = result.get('unit', '')
        quantity = result.get('quantity', 0)
        
        # 根据单位类型选择适当的包装数计算
        if unit in ['件', '箱']:
            # 计算包装数量（二级*三级，如果无三级则仅二级）
            packaging_count = level2 * (level3 or 1)
            
            # 数量×包装数量
            new_quantity = quantity * packaging_count
            
            logger.info(f"赠品{unit}单位处理: 数量: {quantity} -> {new_quantity}, 单价: 0, 单位: {unit} -> 瓶")
            
            result['quantity'] = new_quantity
            result['unit'] = '瓶'
        elif unit in ['提', '盒'] and level3 is not None:
            # 对于三级规格的提/盒，类似件处理
            new_quantity = quantity * level3
            
            logger.info(f"赠品{unit}单位(三级规格)处理: 数量: {quantity} -> {new_quantity}, 单价: 0, 单位: {unit} -> 瓶")
            
            result['quantity'] = new_quantity
            result['unit'] = '瓶'
        else:
            # 其他情况保持不变
            logger.info(f"赠品{unit}单位处理: 保持原样 数量: {quantity}, 单价: 0, 单位: {unit}")
        
        # 确保单价为0
        result['price'] = 0
        
        return result 