from datetime import UTC, datetime
from pathlib import Path
from typing import TypedDict

from zbt.core.config import get_settings
from zbt.domains.knowledge.repository import KnowledgeRepository
from zbt.domains.knowledge.service import KnowledgeService
from zbt.infrastructure.milvus.knowledge_index import MilvusKnowledgeIndex
from zbt.infrastructure.mysql.knowledge_repositories import SqlAlchemyKnowledgeRepository
from zbt.infrastructure.mysql.sessions import (
    DatabaseName,
    create_mysql_engine,
    create_session_factory,
)


def resolve_seed_root() -> Path:
    """从项目根目录或 backend 工作目录定位知识库种子文件。"""

    candidates = (
        Path.cwd() / "knowledge" / "seed",
        Path.cwd().parent / "knowledge" / "seed",
    )
    for candidate in candidates:
        if candidate.is_dir():
            return candidate
    raise FileNotFoundError("未找到 knowledge/seed，请从项目根目录或 backend 目录执行命令。")


class SeedDocumentConfig(TypedDict):
    file_name: str
    title: str
    document_type: str
    product_code: str | None


SEED_ROOT = resolve_seed_root()
SEED_DOCUMENTS: tuple[SeedDocumentConfig, ...] = (
    {
        "file_name": "安心医疗险保险条款.md",
        "title": "安心医疗险保险条款",
        "document_type": "INSURANCE_TERMS",
        "product_code": "MED-BASIC",
    },
    {
        "file_name": "医疗费用报销协助服务规则.md",
        "title": "医疗费用报销协助服务规则",
        "document_type": "SERVICE_RULES",
        "product_code": None,
    },
    {
        "file_name": "家庭意外保障常见问题.md",
        "title": "家庭意外保障常见问题",
        "document_type": "FAQ",
        "product_code": "ACC-FAMILY",
    },
)


def seed_documents(
    service: KnowledgeService,
    repository: KnowledgeRepository,
    seed_root: Path,
    documents: tuple[SeedDocumentConfig, ...] = SEED_DOCUMENTS,
) -> list[str]:
    """重建种子知识索引，兼容从 SQL 恢复出的已发布文档。"""
    existing_by_source = {
        document.source_name: document for document in repository.list_documents()
    }
    ready_sources: list[str] = []
    for config in documents:
        source_name = config["file_name"]
        document = existing_by_source.get(source_name)
        if document is None:
            created = service.create_document(
                title=config["title"],
                document_type=config["document_type"],
                source_name=source_name,
                product_code=(
                    config["product_code"] if config["product_code"] is not None else None
                ),
                content=(seed_root / source_name).read_text(encoding="utf-8"),
                created_by="SYSTEM_SEED",
            )
            document_id = str(created["document_id"])
        else:
            document_id = document.id
        service.index_document(document_id)
        service.test_search(
            document_id,
            config["title"],
            tested_by="SYSTEM_SEED",
        )
        service.publish_document(document_id)
        ready_sources.append(source_name)
    return ready_sources


def main() -> None:
    settings = get_settings()
    engine = create_mysql_engine(settings, DatabaseName.CORE)
    repository = SqlAlchemyKnowledgeRepository(create_session_factory(engine))
    service = KnowledgeService(
        repository,
        lambda: datetime.now(UTC),
        MilvusKnowledgeIndex(settings),
    )
    for source_name in seed_documents(
        service,
        repository,
        SEED_ROOT,
    ):
        print(f"knowledge ready: {source_name}")


if __name__ == "__main__":
    main()
