"""
知识库业务逻辑服务
"""
from math import ceil
from typing import List, Optional, Tuple, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_
from datetime import datetime
import uuid

from app.sample.models.knowledge_base import KnowledgeBase
from app.sample.schemas.knowledge_base import (
    KnowledgeBaseCreate, 
    KnowledgeBaseUpdate,
    KnowledgeBaseResponse
)
from app.services.milvus_service import milvus_service
from app.schemas.base import PaginationSchema

class KnowledgeBaseService:
    
    async def get_list(
        self, 
        db: AsyncSession,
        page: int = 1,
        page_size: int = 10,
        keyword: Optional[str] = None,
        status: Optional[str] = None
    ) -> Tuple[List[KnowledgeBase], PaginationSchema]:
        """获取知识库列表"""
        
        # --- 同步 Milvus 数据 ---
        try:
            # 1. 获取 Milvus 所有集合
            milvus_names = milvus_service.client.list_collections()
            
            # 2. 获取 DB 中已有的集合
            result = await db.execute(select(KnowledgeBase).where(KnowledgeBase.is_deleted == 0))
            existing_kbs = result.scalars().all()
            existing_map = {kb.collection_name: kb for kb in existing_kbs}
            
            # 3. 同步逻辑
            has_changes = False
            for m_name in milvus_names:
                # 获取统计信息
                try:
                    stats = milvus_service.client.get_collection_stats(m_name)
                    row_count = int(stats.get("row_count", 0))
                except Exception:
                    row_count = 0

                if m_name not in existing_map:
                    # 新增
                    new_kb = KnowledgeBase(
                        id=str(uuid.uuid4()),
                        name=m_name,
                        collection_name=m_name,
                        description="Synced from Milvus",
                        status="normal",
                        document_count=row_count,
                        created_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        updated_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    )
                    db.add(new_kb)
                    has_changes = True
                else:
                    # 更新统计
                    kb = existing_map[m_name]
                    if kb.document_count != row_count:
                        kb.document_count = row_count
                        # kb.created_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 统计更新不一定更新时间
                        has_changes = True
            
            if has_changes:
                await db.commit()
                
        except Exception as e:
            # 同步失败不影响查询，只打印日志
            print(f"Sync Milvus collections failed: {e}")
        # ----------------------

        query = select(KnowledgeBase).where(KnowledgeBase.is_deleted == 0)
        
        if keyword:
            query = query.where(or_(
                KnowledgeBase.name.like(f"%{keyword}%"),
                KnowledgeBase.collection_name.like(f"%{keyword}%")
            ))
        
        if status:
            query = query.where(KnowledgeBase.status == status)

        # 计算总数
        count_query = select(func.count()).select_from(query.subquery())
        total = await db.scalar(count_query) or 0

        # 分页查询
        query = query.order_by(KnowledgeBase.created_time.desc()).offset((page - 1) * page_size).limit(page_size)
        result = await db.execute(query)
        items = result.scalars().all()

        total_pages = ceil(total / page_size) if page_size else 0
        
        meta = PaginationSchema(
            page=page,
            page_size=page_size,
            total=total,
            total_pages=total_pages,
        )
        
        return items, meta

    async def create(self, db: AsyncSession, payload: KnowledgeBaseCreate) -> KnowledgeBase:
        """创建新知识库"""
        # 1. 检查 DB 是否已存在
        exists = await db.execute(select(KnowledgeBase).where(
            KnowledgeBase.collection_name == payload.collection_name,
            KnowledgeBase.is_deleted == 0
        ))
        if exists.scalars().first():
            raise ValueError("知识库集合名称已存在")

        # 2. 检查 Milvus 是否已存在
        if milvus_service.has_collection(payload.collection_name):
            raise ValueError("Milvus集合已存在，请使用其他名称")

        try:
            # 3. 创建 Milvus 集合
            milvus_service.create_collection(
                name=payload.collection_name,
                dimension=payload.dimension,
                description=payload.description or ""
            )

            # 4. 创建 DB 记录
            now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            new_kb = KnowledgeBase(
                id=str(uuid.uuid4()),
                name=payload.name,
                collection_name=payload.collection_name,
                description=payload.description,
                status=payload.status or "normal",
                created_time=now,
                updated_time=now
            )
            db.add(new_kb)
            await db.commit()
            await db.refresh(new_kb)

            return new_kb
        except Exception as e:
            await db.rollback()
            raise e

    async def update(self, db: AsyncSession, id: str, payload: KnowledgeBaseUpdate) -> KnowledgeBase:
        """更新知识库信息"""
        result = await db.execute(select(KnowledgeBase).where(KnowledgeBase.id == id, KnowledgeBase.is_deleted == 0))
        kb = result.scalars().first()
        
        if not kb:
            raise ValueError("知识库不存在")

        try:
            if payload.name is not None:
                kb.name = payload.name
            if payload.description is not None:
                kb.description = payload.description
                # 同步更新 Milvus 描述
                milvus_service.update_collection_description(kb.collection_name, payload.description)
            if payload.status is not None:
                kb.status = payload.status
            
            kb.created_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            await db.commit()
            await db.refresh(kb)
            
            return kb
        except Exception as e:
            await db.rollback()
            raise e

    async def update_status(self, db: AsyncSession, id: str, status: str) -> KnowledgeBase:
        """更新知识库状态（启用/禁用）"""
        result = await db.execute(select(KnowledgeBase).where(KnowledgeBase.id == id, KnowledgeBase.is_deleted == 0))
        kb = result.scalars().first()
        
        if not kb:
            raise ValueError("知识库不存在")
        
        try:
            kb.status = status
            kb.created_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            # 可选：同步操作 Milvus Load/Release
            if status == "normal":
                milvus_service.set_collection_state(kb.collection_name, "load")
            elif status == "disabled":
                milvus_service.set_collection_state(kb.collection_name, "release")
                
            await db.commit()
            await db.refresh(kb)
            return kb
        except Exception as e:
            await db.rollback()
            raise e

    async def delete(self, db: AsyncSession, id: str) -> None:
        """删除知识库"""
        result = await db.execute(select(KnowledgeBase).where(KnowledgeBase.id == id))
        kb = result.scalars().first()
        
        if not kb:
            raise ValueError("知识库不存在")

        try:
            # 1. 删除 Milvus 集合 (强制删除)
            milvus_service.drop_collection(kb.collection_name)
            
            # 2. 软删除 DB 记录
            kb.is_deleted = 1
            kb.created_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            await db.commit()
        except Exception as e:
            await db.rollback()
            raise e

knowledge_base_service = KnowledgeBaseService()
