"""
样本中心服务层
从 sample_view.py 提取的SQL查询逻辑
"""
import sys
import os

# 添加src目录到Python路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../..'))

import logging
import uuid
from typing import Optional, List, Dict, Any, Tuple
from datetime import datetime, timezone
from app.base.async_mysql_connection import get_db_connection

logger = logging.getLogger(__name__)

# 表名映射
TABLE_MAP = {
    'basis': 't_basis_of_preparation',
    'work': 't_work_of_preparation',
    'job': 't_job_of_preparation'
}


def get_table_name(source_type: str) -> Optional[str]:
    """根据source_type获取表名"""
    return TABLE_MAP.get(source_type)


class SampleService:
    """样本中心服务类 - 使用 SQL 查询方式"""
    
    def __init__(self):
        """初始化服务"""
        pass
    
    # ==================== 文档管理 ====================
    
    async def batch_enter_knowledge_base(self, doc_ids: List[str], username: str) -> Tuple[int, str]:
        """批量将文档加入知识库"""
        conn = get_db_connection()
        if not conn:
            return 0, "数据库连接失败"
        
        cursor = conn.cursor()
        
        try:
            # 批量更新主表 t_document_main
            placeholders = ', '.join(['%s'] * len(doc_ids))
            
            # 更新主表
            sql_main = f"""
                UPDATE t_document_main 
                SET whether_to_enter = 1, updated_time = NOW() 
                WHERE id IN ({placeholders}) AND whether_to_enter = 0
            """
            cursor.execute(sql_main, doc_ids)
            affected_rows = cursor.rowcount
            
            # 尝试更新对应的子表以保持同步
            try:
                cursor.execute(f"SELECT id, source_type, source_id FROM t_document_main WHERE id IN ({placeholders})", doc_ids)
                docs = cursor.fetchall()
                
                for doc_row in docs:
                    d_id, s_type, s_id = doc_row
                    if s_type and s_id:
                        sub_table = get_table_name(s_type)
                        if sub_table:
                            sub_sql = f"UPDATE {sub_table} SET whether_to_enter = 1, updated_at = NOW(), updated_by = %s WHERE id = %s"
                            try:
                                cursor.execute(sub_sql, (username, s_id))
                            except Exception as sub_e:
                                logger.error(f"更新子表 {sub_table} 失败: {sub_e}")
            except Exception as sync_e:
                logger.error(f"同步更新子表失败: {sync_e}")
            
            conn.commit()
            
            message = f"成功将 {affected_rows} 条数据加入知识库"
            if affected_rows < len(doc_ids):
                message += f"（跳过了 {len(doc_ids) - affected_rows} 条已入库数据或未找到数据）"
            
            return affected_rows, message
        except Exception as e:
            logger.exception("批量操作失败")
            conn.rollback()
            return 0, f"批量操作失败: {str(e)}"
        finally:
            cursor.close()
            conn.close()
    
    async def batch_delete_documents(self, doc_ids: List[str]) -> Tuple[int, str]:
        """批量删除文档"""
        conn = get_db_connection()
        if not conn:
            return 0, "数据库连接失败"
        
        cursor = conn.cursor()
        
        try:
            if not doc_ids:
                return 0, "未指定要删除的文档 ID"
            
            placeholders = ', '.join(['%s'] * len(doc_ids))
            
            # 尝试同步删除子表中的数据
            try:
                cursor.execute(f"SELECT source_type, source_id FROM t_document_main WHERE id IN ({placeholders})", doc_ids)
                docs = cursor.fetchall()
                
                for doc_row in docs:
                    s_type, s_id = doc_row
                    if s_type and s_id:
                        sub_table = get_table_name(s_type)
                        if sub_table:
                            sub_sql = f"DELETE FROM {sub_table} WHERE id = %s"
                            try:
                                cursor.execute(sub_sql, (s_id,))
                            except Exception as sub_e:
                                logger.error(f"删除子表 {sub_table} 数据失败: {sub_e}")
            except Exception as sync_e:
                logger.error(f"同步删除子表数据失败: {sync_e}")
            
            # 删除主表 t_document_main 中的数据
            sql_main = f"DELETE FROM t_document_main WHERE id IN ({placeholders})"
            cursor.execute(sql_main, doc_ids)
            affected_rows = cursor.rowcount
            
            conn.commit()
            
            return affected_rows, f"成功删除 {affected_rows} 条文档数据"
        except Exception as e:
            logger.exception("批量删除失败")
            conn.rollback()
            return 0, f"批量删除失败: {str(e)}"
        finally:
            cursor.close()
            conn.close()
    
    async def get_document_list(
        self,
        whether_to_enter: Optional[int] = None,
        keyword: Optional[str] = None,
        table_type: Optional[str] = None,
        page: int = 1,
        size: int = 50
    ) -> Tuple[List[Dict[str, Any]], int, int, int]:
        """获取文档列表（从主表查询）"""
        conn = get_db_connection()
        if not conn:
            return [], 0, 0, 0
        
        cursor = conn.cursor()
        
        try:
            where_clauses = []
            params = []
            
            if table_type:
                where_clauses.append("source_type = %s")
                params.append(table_type)
            if whether_to_enter is not None:
                where_clauses.append("whether_to_enter = %s")
                params.append(whether_to_enter)
            if keyword:
                where_clauses.append("(title LIKE %s OR content LIKE %s)")
                params.extend([f"%{keyword}%", f"%{keyword}%"])
            
            where_sql = " WHERE " + " AND ".join(where_clauses) if where_clauses else ""
            offset = (page - 1) * size
            
            sql = f"SELECT * FROM t_document_main {where_sql} ORDER BY created_time DESC LIMIT %s OFFSET %s"
            params.extend([size, offset])
            
            cursor.execute(sql, tuple(params))
            columns = [desc[0] for desc in cursor.description]
            items = []
            for row in cursor.fetchall():
                item = dict(zip(columns, row))
                # 格式化时间
                for key in ['created_time', 'updated_time', 'release_date']:
                    if item.get(key) and hasattr(item[key], 'isoformat'):
                        item[key] = item[key].isoformat()
                items.append(item)
            
            # 总数
            count_sql = f"SELECT COUNT(*) FROM t_document_main {where_sql}"
            cursor.execute(count_sql, tuple(params[:-2]))
            total = cursor.fetchone()[0]
            
            # 统计数据
            cursor.execute("SELECT COUNT(*) FROM t_document_main")
            all_total = cursor.fetchone()[0]
            cursor.execute("SELECT COUNT(*) FROM t_document_main WHERE whether_to_enter = 1")
            total_entered = cursor.fetchone()[0]
            
            return items, total, all_total, total_entered
        except Exception as e:
            logger.exception("获取文档列表失败")
            return [], 0, 0, 0
        finally:
            cursor.close()
            conn.close()
    
    async def get_document_detail(self, doc_id: str) -> Optional[Dict[str, Any]]:
        """获取文档详情（关联查询子表）"""
        conn = get_db_connection()
        if not conn:
            return None
        
        cursor = conn.cursor()
        
        try:
            # 查询主表
            cursor.execute("SELECT * FROM t_document_main WHERE id = %s", (doc_id,))
            main_row = cursor.fetchone()
            if not main_row:
                return None
            
            columns = [desc[0] for desc in cursor.description]
            doc = dict(zip(columns, main_row))
            
            # 查询子表
            source_type = doc.get('source_type')
            source_id = doc.get('source_id')
            table_name = TABLE_MAP.get(source_type)
            
            if table_name and source_id:
                cursor.execute(f"SELECT * FROM {table_name} WHERE id = %s", (source_id,))
                sub_row = cursor.fetchone()
                if sub_row:
                    sub_columns = [desc[0] for desc in cursor.description]
                    sub_data = dict(zip(sub_columns, sub_row))
                    
                    # 将子表字段映射到通用字段名
                    if source_type == 'basis':
                        doc['standard_no'] = sub_data.get('standard_number')
                        doc['issuing_authority'] = sub_data.get('issuing_authority')
                        doc['release_date'] = str(sub_data.get('release_date')) if sub_data.get('release_date') else None
                        doc['document_type'] = sub_data.get('document_type')
                        doc['professional_field'] = sub_data.get('professional_field')
                        doc['validity'] = sub_data.get('validity')
                    elif source_type == 'work':
                        doc['project_name'] = sub_data.get('project_name')
                        doc['project_section'] = sub_data.get('project_section')
                        doc['issuing_authority'] = sub_data.get('compiling_unit')
                        doc['release_date'] = str(sub_data.get('compiling_date')) if sub_data.get('compiling_date') else None
                    elif source_type == 'job':
                        doc['issuing_authority'] = sub_data.get('issuing_department')
                        doc['document_type'] = sub_data.get('document_type')
                        doc['release_date'] = str(sub_data.get('publish_date')) if sub_data.get('publish_date') else None
            
            # 格式化主表时间
            if doc.get('created_time'):
                doc['created_time'] = doc['created_time'].isoformat()
            if doc.get('updated_time'):
                doc['updated_time'] = doc['updated_time'].isoformat()
            if doc.get('release_date') and not isinstance(doc['release_date'], str):
                doc['release_date'] = doc['release_date'].isoformat()
            
            return doc
        except Exception as e:
            logger.exception("获取文档详情失败")
            return None
        finally:
            cursor.close()
            conn.close()
    
    async def add_document(self, doc_data: Dict[str, Any], user_id: str) -> Tuple[bool, str, Optional[str]]:
        """添加新文档（同步主表和子表）"""
        conn = get_db_connection()
        if not conn:
            return False, "数据库连接失败", None
        
        cursor = conn.cursor()
        
        try:
            doc_id = str(uuid.uuid4())
            source_id = str(uuid.uuid4())
            table_name = TABLE_MAP.get(doc_data.get('table_type'), "t_basis_of_preparation")
            
            # 插入子表
            table_type = doc_data.get('table_type')
            if table_type == 'basis':
                cursor.execute(
                    f"INSERT INTO {table_name} (id, chinese_name, created_by) VALUES (%s, %s, %s)",
                    (source_id, doc_data.get('title'), user_id)
                )
            elif table_type == 'work':
                cursor.execute(
                    f"INSERT INTO {table_name} (id, plan_name, created_by) VALUES (%s, %s, %s)",
                    (source_id, doc_data.get('title'), user_id)
                )
            elif table_type == 'job':
                cursor.execute(
                    f"INSERT INTO {table_name} (id, file_name, created_by) VALUES (%s, %s, %s)",
                    (source_id, doc_data.get('title'), user_id)
                )
            
            # 插入主表
            cursor.execute("""
                INSERT INTO t_document_main 
                (id, title, content, created_by, source_type, source_id, whether_to_enter, 
                 primary_category_id, secondary_category_id, year, file_url, file_extension) 
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """, (doc_id, doc_data.get('title'), doc_data.get('content'), user_id, 
                  doc_data.get('table_type'), source_id, 0, doc_data.get('primary_category_id'), 
                  doc_data.get('secondary_category_id'), doc_data.get('year'), 
                  doc_data.get('file_url'), doc_data.get('file_extension')))
            
            conn.commit()
            return True, "文档添加成功", doc_id
        except Exception as e:
            logger.exception("添加文档失败")
            conn.rollback()
            return False, str(e), None
        finally:
            cursor.close()
            conn.close()
    
    async def get_basic_info_list(
        self,
        type: str,
        page: int,
        size: int,
        keyword: Optional[str] = None,
        **filters
    ) -> Tuple[List[Dict[str, Any]], int]:
        """获取基本信息列表（支持多条件检索）"""
        conn = get_db_connection()
        if not conn:
            return [], 0
        
        cursor = conn.cursor()
        
        try:
            # 根据类型选择表名和字段映射
            if type == 'basis':
                table_name = "t_basis_of_preparation"
                fields = "id, chinese_name as title, standard_number as standard_no, issuing_authority, release_date, document_type, professional_field, validity, created_by, created_time as created_at"
                field_map = {
                    'title': 'chinese_name',
                    'standard_no': 'standard_number',
                    'issuing_authority': 'issuing_authority',
                    'release_date': 'release_date',
                    'document_type': 'document_type',
                    'professional_field': 'professional_field',
                    'validity': 'validity'
                }
            elif type == 'work':
                table_name = "t_work_of_preparation"
                fields = "id, plan_name as title, NULL as standard_no, compiling_unit as issuing_authority, compiling_date as release_date, NULL as document_type, NULL as professional_field, NULL as validity, created_by, created_time as created_at"
                field_map = {
                    'title': 'plan_name',
                    'issuing_authority': 'compiling_unit',
                    'release_date': 'compiling_date'
                }
            elif type == 'job':
                table_name = "t_job_of_preparation"
                fields = "id, file_name as title, NULL as standard_no, issuing_department as issuing_authority, publish_date as release_date, document_type, NULL as professional_field, NULL as validity, created_by, created_time as created_at"
                field_map = {
                    'title': 'file_name',
                    'issuing_authority': 'issuing_department',
                    'release_date': 'publish_date',
                    'document_type': 'document_type'
                }
            else:
                return [], 0
            
            where_clauses = []
            params = []
            
            # 统一关键字搜索
            if keyword:
                if type == 'basis':
                    where_clauses.append("(chinese_name LIKE %s OR standard_number LIKE %s)")
                    params.extend([f"%{keyword}%", f"%{keyword}%"])
                elif type == 'work':
                    where_clauses.append("plan_name LIKE %s")
                    params.append(f"%{keyword}%")
                elif type == 'job':
                    where_clauses.append("file_name LIKE %s")
                    params.append(f"%{keyword}%")
            
            # 精细化检索
            for filter_key, filter_value in filters.items():
                if filter_value and filter_key in field_map:
                    db_field = field_map[filter_key]
                    if filter_key.endswith('_start'):
                        where_clauses.append(f"{db_field} >= %s")
                        params.append(filter_value)
                    elif filter_key.endswith('_end'):
                        where_clauses.append(f"{db_field} <= %s")
                        params.append(filter_value)
                    else:
                        where_clauses.append(f"{db_field} LIKE %s")
                        params.append(f"%{filter_value}%")
            
            where_sql = " WHERE " + " AND ".join(where_clauses) if where_clauses else ""
            
            # 分页查询
            offset = (page - 1) * size
            sql = f"SELECT {fields} FROM {table_name}{where_sql} ORDER BY created_at DESC LIMIT %s OFFSET %s"
            params.extend([size, offset])
            
            cursor.execute(sql, tuple(params))
            columns = [desc[0] for desc in cursor.description]
            items = []
            for row in cursor.fetchall():
                item = dict(zip(columns, row))
                # 格式化日期
                for key in ['release_date', 'created_at']:
                    if item.get(key) and hasattr(item[key], 'isoformat'):
                        item[key] = item[key].isoformat()
                    elif item.get(key):
                        item[key] = str(item[key])
                items.append(item)
            
            # 总数查询
            count_sql = f"SELECT COUNT(*) FROM {table_name}{where_sql}"
            cursor.execute(count_sql, tuple(params[:-2]))
            total = cursor.fetchone()[0]
            
            return items, total
        except Exception as e:
            logger.exception("查询基本信息失败")
            return [], 0
        finally:
            cursor.close()
            conn.close()
    
    async def edit_document(self, doc_data: Dict[str, Any]) -> Tuple[bool, str]:
        """编辑文档（同步主表和子表）"""
        conn = get_db_connection()
        if not conn:
            return False, "数据库连接失败"
        
        cursor = conn.cursor()
        
        try:
            doc_id = doc_data.get('id')
            source_id = doc_data.get('source_id')
            table_type = doc_data.get('table_type')
            
            if not doc_id or not source_id:
                return False, "缺少ID参数"
            
            table_name = TABLE_MAP.get(table_type, "t_basis_of_preparation")
            
            # 更新子表内容
            if table_type == 'basis':
                cursor.execute(f"""
                    UPDATE {table_name} 
                    SET chinese_name = %s, standard_number = %s, issuing_authority = %s, 
                        release_date = %s, document_type = %s, professional_field = %s, validity = %s
                    WHERE id = %s
                """, (doc_data.get('title'), doc_data.get('standard_no'), doc_data.get('issuing_authority'), 
                      doc_data.get('release_date'), doc_data.get('document_type'), 
                      doc_data.get('professional_field'), doc_data.get('validity'), source_id))
            elif table_type == 'work':
                cursor.execute(f"""
                    UPDATE {table_name} 
                    SET plan_name = %s, project_name = %s, project_section = %s, 
                        compiling_unit = %s, compiling_date = %s
                    WHERE id = %s
                """, (doc_data.get('title'), doc_data.get('project_name'), doc_data.get('project_section'), 
                      doc_data.get('issuing_authority'), doc_data.get('release_date'), source_id))
            elif table_type == 'job':
                cursor.execute(f"""
                    UPDATE {table_name} 
                    SET file_name = %s, issuing_department = %s, document_type = %s, publish_date = %s
                    WHERE id = %s
                """, (doc_data.get('title'), doc_data.get('issuing_authority'), 
                      doc_data.get('document_type'), doc_data.get('release_date'), source_id))
            
            # 更新主表内容
            cursor.execute("""
                UPDATE t_document_main 
                SET title = %s, content = %s, updated_time = NOW(),
                    primary_category_id = %s, secondary_category_id = %s, year = %s,
                    file_url = %s, file_extension = %s
                WHERE id = %s
            """, (doc_data.get('title'), doc_data.get('content'), doc_data.get('primary_category_id'), 
                  doc_data.get('secondary_category_id'), doc_data.get('year'), 
                  doc_data.get('file_url'), doc_data.get('file_extension'), doc_id))
            
            conn.commit()
            return True, "文档更新成功"
        except Exception as e:
            logger.exception("编辑文档失败")
            conn.rollback()
            return False, str(e)
        finally:
            cursor.close()
            conn.close()
    
    async def enter_document(self, doc_id: str, username: str) -> Tuple[bool, str]:
        """文档入库"""
        conn = get_db_connection()
        if not conn:
            return False, "数据库连接失败"
        
        cursor = conn.cursor()
        
        try:
            # 更新主表
            cursor.execute("UPDATE t_document_main SET whether_to_enter = 1, updated_time = NOW() WHERE id = %s", (doc_id,))
            
            # 尝试同步更新子表
            try:
                cursor.execute("SELECT source_type, source_id FROM t_document_main WHERE id = %s", (doc_id,))
                res = cursor.fetchone()
                if res and res[0] and res[1]:
                    s_type, s_id = res
                    sub_table = get_table_name(s_type)
                    if sub_table:
                        sub_sql = f"UPDATE {sub_table} SET whether_to_enter = 1, updated_at = NOW(), updated_by = %s WHERE id = %s"
                        try:
                            cursor.execute(sub_sql, (username, s_id))
                        except Exception as sub_e:
                            logger.error(f"入库同步子表 {sub_table} 失败: {sub_e}")
            except Exception as sync_e:
                logger.error(f"入库同步子表异常: {sync_e}")
            
            conn.commit()
            return True, "入库成功"
        except Exception as e:
            logger.exception("入库失败")
            conn.rollback()
            return False, str(e)
        finally:
            cursor.close()
            conn.close()
            conn.close()

    # ==================== 文档转换 ====================
    
    async def get_document_source_type(self, doc_id: str) -> Optional[str]:
        """获取文档的source_type"""
        conn = get_db_connection()
        if not conn:
            return None
        
        cursor = conn.cursor()
        
        try:
            cursor.execute("SELECT source_type FROM t_document_main WHERE id = %s", (doc_id,))
            res = cursor.fetchone()
            return res[0] if res else None
        except Exception as e:
            logger.exception(f"获取文档source_type失败: {e}")
            return None
        finally:
            cursor.close()
            conn.close()
    
    async def get_document_title(self, doc_id: str) -> str:
        """获取文档标题"""
        conn = get_db_connection()
        if not conn:
            return "文档"
        
        cursor = conn.cursor()
        
        try:
            cursor.execute("SELECT title FROM t_document_main WHERE id = %s", (doc_id,))
            res = cursor.fetchone()
            return res[0] if res else "文档"
        except Exception as e:
            logger.exception(f"获取文档标题失败: {e}")
            return "文档"
        finally:
            cursor.close()
            conn.close()
    
    async def update_conversion_progress(self, doc_id: str, status: int, progress: int, 
                                        converted_file_name: Optional[str] = None,
                                        error_message: Optional[str] = None) -> bool:
        """更新文档转换进度
        
        Args:
            doc_id: 文档ID
            status: 转换状态 (0=未转换, 1=转换中, 2=已完成, 3=失败)
            progress: 转换进度 (0-100)
            converted_file_name: 转换后的文件名
            error_message: 错误信息
        """
        conn = get_db_connection()
        if not conn:
            return False
        
        cursor = conn.cursor()
        
        try:
            if error_message:
                # 转换失败
                cursor.execute(
                    "UPDATE t_document_main SET conversion_status = %s, conversion_error = %s WHERE id = %s",
                    (status, error_message, doc_id)
                )
            elif converted_file_name:
                # 转换完成
                cursor.execute(
                    "UPDATE t_document_main SET conversion_status = %s, conversion_progress = %s, converted_file_name = %s WHERE id = %s",
                    (status, progress, converted_file_name, doc_id)
                )
            else:
                # 更新进度
                cursor.execute(
                    "UPDATE t_document_main SET conversion_status = %s, conversion_progress = %s WHERE id = %s",
                    (status, progress, doc_id)
                )
            
            conn.commit()
            return True
        except Exception as e:
            logger.exception(f"更新转换进度失败: {e}")
            conn.rollback()
            return False
        finally:
            cursor.close()
            conn.close()
