"""
烟草订单处理器

处理烟草公司特定格式的订单明细文件，生成银豹采购单
"""

import os
import datetime
import pandas as pd
import xlrd
import xlwt
from xlutils.copy import copy
from openpyxl import load_workbook
from typing import Optional, Dict, Any, List, Tuple
from pathlib import Path

from app.core.processors.base import BaseProcessor
from app.core.utils.log_utils import get_logger
from app.core.utils.string_utils import parse_monetary_string
from app.core.utils.dialog_utils import show_custom_dialog

logger = get_logger(__name__)


class TobaccoProcessor(BaseProcessor):
    """烟草订单处理器
    
    处理烟草公司订单明细文件，提取商品信息并生成标准银豹采购单格式
    """
    
    def __init__(self, config: Dict[str, Any]):
        """初始化烟草订单处理器
        
        Args:
            config: 配置信息
        """
        super().__init__(config)
        self.description = "处理烟草公司订单明细文件"
        self.template_file = config.get('Paths', 'template_file', fallback='templates/银豹-采购单模板.xls')
        
        # 输出目录配置
        self.result_dir = Path(config.get_path('Paths', 'result_folder', fallback='data/result', create=True) if hasattr(config, 'get_path') else os.path.abspath('data/result'))
        self.result_dir.mkdir(exist_ok=True)
        
        # 默认输出文件名
        self.default_output_name = "银豹采购单_烟草公司.xls"
    
    def can_process(self, file_path: Path) -> bool:
        """判断是否为烟草订单文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            是否能处理该文件
        """
        if not self.validate_input(file_path):
            return False
        
        # 检查文件名特征
        filename = file_path.name
        tobacco_keywords = ['烟草', '卷烟', '订单明细', 'tobacco', '烟']
        
        # 检查文件内容特征
        try:
            df = self._read_excel_safely(file_path, nrows=5)
            required_columns = ['商品', '盒码', '订单量']
            
            # 检查文件名或内容特征
            filename_match = any(keyword in filename for keyword in tobacco_keywords)
            content_match = all(col in df.columns for col in required_columns)
            
            if filename_match or content_match:
                self.logger.info(f"识别为烟草订单文件: {filename}")
                return True
            
            return False
            
        except Exception as e:
            self.logger.warning(f"检查文件内容时出错: {e}")
            # 如果无法读取内容，仅基于文件名判断
            return any(keyword in filename for keyword in tobacco_keywords)
    
    def process(self, input_file: Path, output_dir: Path) -> Optional[Path]:
        """处理烟草订单
        
        Args:
            input_file: 输入文件路径
            output_dir: 输出目录路径
            
        Returns:
            输出文件路径，处理失败返回None
        """
        self.log_processing_start(input_file)
        
        try:
            # 读取订单信息（时间和总金额）
            order_info = self._read_order_info(input_file)
            if not order_info:
                self.logger.error(f"读取订单信息失败: {input_file}")
                self.log_processing_end(input_file, success=False)
                return None
            
            order_time, total_amount = order_info
            self.logger.info(f"订单信息 - 时间: {order_time}, 总金额: {total_amount}")
            
            # 读取订单数据
            order_data = self._read_order_data(input_file)
            if order_data is None or order_data.empty:
                self.logger.error(f"读取订单数据失败或数据为空: {input_file}")
                self.log_processing_end(input_file, success=False)
                return None
            
            self.logger.info(f"成功读取订单数据，共{len(order_data)}条记录")
            
            # 生成输出文件路径
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            output_filename = f"银豹采购单_烟草公司_{timestamp}.xls"
            output_file = output_dir / output_filename
            
            # 确保输出目录存在
            output_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 生成银豹采购单
            result = self._generate_pospal_order(order_data, order_time, output_file)
            
            if result:
                self.logger.info(f"采购单生成成功: {output_file}")
                self.log_processing_end(input_file, output_file, success=True)
                
                # 显示处理结果
                self._show_processing_result(output_file, order_time, len(order_data), total_amount)
                
                return output_file
            else:
                self.logger.error("生成银豹采购单失败")
                self.log_processing_end(input_file, success=False)
                return None
                
        except Exception as e:
            self.logger.error(f"处理烟草订单时发生错误: {e}", exc_info=True)
            self.log_processing_end(input_file, success=False)
            return None
    
    def get_required_columns(self) -> List[str]:
        """返回需要的列名列表"""
        return ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
    
    def get_supported_extensions(self) -> List[str]:
        """支持的文件扩展名"""
        return ['.xlsx', '.xls']
    
    def _read_order_info(self, file_path: Path) -> Optional[Tuple[str, float]]:
        """读取订单信息（时间和总金额）
        
        Args:
            file_path: 文件路径
            
        Returns:
            包含订单时间和总金额的元组或None
        """
        try:
            wb_info = load_workbook(file_path, data_only=True)
            ws_info = wb_info.active
            
            # 从指定单元格读取订单信息
            order_time = ws_info["H1"].value or "（空）"
            total_amount = ws_info["H3"].value or 0.0
            
            self.logger.info(f"成功读取订单信息: 时间={order_time}, 总金额={total_amount}")
            return (order_time, total_amount)
            
        except Exception as e:
            self.logger.error(f"读取订单信息出错: {e}")
            return None
    
    def _read_order_data(self, file_path: Path) -> Optional[pd.DataFrame]:
        """读取订单数据
        
        Args:
            file_path: 文件路径
            
        Returns:
            订单数据DataFrame或None
        """
        columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
        
        try:
            df_old = self._read_excel_safely(file_path, header=None, skiprows=3, names=columns)
            
            # 过滤订单量不为0的数据，并计算采购量和单价
            df_filtered = df_old[df_old['订单量'] != 0].copy()
            
            if df_filtered.empty:
                self.logger.warning("没有订单量不为0的记录")
                return None
            
            # 计算采购量和单价
            df_filtered['采购量'] = df_filtered['订单量'] * 10  # 烟草订单通常需要乘以10
            df_filtered['采购单价'] = df_filtered['金额'] / df_filtered['采购量']
            df_filtered = df_filtered.reset_index(drop=True)
            
            self.logger.info(f"成功处理订单数据，有效记录数: {len(df_filtered)}")
            return df_filtered
            
        except Exception as e:
            self.logger.error(f"读取订单数据失败: {e}")
            return None

    def _generate_pospal_order(self, order_data: pd.DataFrame, order_time: str, output_file: Path) -> bool:
        """生成银豹采购单
        
        Args:
            order_data: 订单数据
            order_time: 订单时间
            output_file: 输出文件路径
            
        Returns:
            是否生成成功
        """
        try:
            # 检查模板文件是否存在
            template_path = Path(self.template_file)
            if not template_path.exists():
                self.logger.error(f"采购单模板文件不存在: {template_path}")
                return False
            
            self.logger.info(f"使用模板文件: {template_path}")
            
            # 打开模板，准备写入
            template_rd = xlrd.open_workbook(str(template_path), formatting_info=True)
            template_wb = copy(template_rd)
            template_ws = template_wb.get_sheet(0)
            
            # 获取模板中的表头列索引
            header_row = template_rd.sheet_by_index(0).row_values(0)
            
            # 查找需要的列索引
            try:
                barcode_col = header_row.index("条码（必填）")
                amount_col = header_row.index("采购量（必填）")
                gift_col = header_row.index("赠送量")
                price_col = header_row.index("采购单价（必填）")
            except ValueError as e:
                self.logger.error(f"模板列查找失败: {e}")
                return False
            
            self.logger.info(f"模板列索引 - 条码:{barcode_col}, 采购量:{amount_col}, 赠送量:{gift_col}, 单价:{price_col}")
            
            # 写入数据到模板
            for i, row in order_data.iterrows():
                template_ws.write(i + 1, barcode_col, row['盒码'])  # 商品条码
                template_ws.write(i + 1, amount_col, int(row['采购量']))  # 采购量
                template_ws.write(i + 1, gift_col, "")  # 赠送量为空
                template_ws.write(i + 1, price_col, round(row['采购单价'], 2))  # 采购单价保留两位小数
            
            # 确保输出目录存在
            output_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 保存输出文件
            template_wb.save(str(output_file))
            
            self.logger.info(f"采购单生成成功: {output_file}")
            return True
            
        except Exception as e:
            self.logger.error(f"生成银豹采购单失败: {e}", exc_info=True)
            return False
    
    def _show_processing_result(self, output_file: Path, order_time: str, total_count: int, total_amount: float):
        """显示处理结果
        
        Args:
            output_file: 输出文件路径
            order_time: 订单时间
            total_count: 处理条目数
            total_amount: 总金额
        """
        try:
            # 创建附加信息
            additional_info = {
                "订单来源": "烟草公司",
                "处理时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
            
            # 格式化金额显示
            parsed = parse_monetary_string(total_amount)
            total_amount = parsed if parsed is not None else 0.0
            amount_display = f"¥{total_amount:.2f}"
            
            # 显示自定义对话框
            show_custom_dialog(
                title="烟草订单处理结果",
                message="烟草订单处理完成",
                result_file=str(output_file),
                time_info=order_time,
                count_info=f"{total_count}个商品",
                amount_info=amount_display,
                additional_info=additional_info
            )
            
            self.logger.info(f"显示处理结果 - 文件:{output_file}, 时间:{order_time}, 数量:{total_count}, 金额:{total_amount}")
            
        except Exception as e:
            self.logger.error(f"显示处理结果时出错: {e}")
    
    def get_latest_tobacco_order(self) -> Optional[Path]:
        """获取最新的烟草订单明细文件（兼容旧接口）
        
        Returns:
            文件路径或None
        """
        try:
            # 获取今日开始时间戳
            today = datetime.date.today()
            today_start = datetime.datetime.combine(today, datetime.time.min).timestamp()
            
            # 查找订单明细文件
            result_dir = Path(self.config.get_path('Paths', 'output_folder', fallback='data/output') if hasattr(self.config, 'get_path') else os.path.abspath('data/output'))
            if not result_dir.exists():
                return None
            
            # 查找符合条件的文件
            candidates = []
            for file_path in result_dir.glob("订单明细*.xlsx"):
                if file_path.stat().st_ctime >= today_start:
                    candidates.append(file_path)
            
            if not candidates:
                self.logger.warning("未找到今天创建的烟草订单明细文件")
                # 返回最新的文件
                all_files = list(result_dir.glob("订单明细*.xlsx"))
                if all_files:
                    all_files.sort(key=lambda x: x.stat().st_ctime, reverse=True)
                    return all_files[0]
                return None
            
            # 返回最新的文件
            candidates.sort(key=lambda x: x.stat().st_ctime, reverse=True)
            latest_file = candidates[0]
            
            self.logger.info(f"找到最新烟草订单明细文件: {latest_file}")
            return latest_file
            
        except Exception as e:
            self.logger.error(f"获取最新烟草订单文件时出错: {e}")
            return None
