import os
import json
import uuid
import logging
from typing import Optional

from ..core.config import settings
from ..services.docx_template import render_template
from ..services.info_pool_service import info_pool_service
from ..services.case_memory_service import case_memory_service

logger = logging.getLogger(__name__)


class DocumentGenerationService:

    async def generate_document(
        self,
        case_id: str,
        template_id: str,
        user_id: str,
        db,
        conversation_context: dict = None,
    ) -> Optional[dict]:
        conn, cur = db

        template_schema = await self._load_template_schema(template_id, db)
        if not template_schema:
            return {"error": "模板不存在", "detail": "template not found"}

        info_pool = await info_pool_service.get(case_id, db)
        if not info_pool:
            return {"error": "案件信息池不存在", "detail": "info pool not found"}

        generation_prompt = self._build_generation_prompt(
            template_schema, info_pool, conversation_context
        )

        import httpx
        deerflow_base = settings.DEERFLOW_LANGGRAPH_URL
        async with httpx.AsyncClient(timeout=60.0) as client:
            try:
                res = await client.post(
                    f"{deerflow_base}/runs/direct",
                    json={
                        "prompt": generation_prompt,
                        "response_format": {"type": "json_object"},
                        "temperature": 0.3,
                    },
                    timeout=60.0,
                )
                ai_response = res.json()
            except Exception as e:
                logger.error(f"AI generation failed: {e}")
                return {"error": "AI生成失败", "detail": str(e)}

        content_str = ai_response.get("content", "")
        try:
            generated_content = json.loads(content_str)
        except (json.JSONDecodeError, TypeError):
            generated_content = {"raw_content": content_str}

        basic_info_snapshot = generated_content.get("basic_info", info_pool.get("basic_info", {}))
        doc_content = generated_content.get("generated_content", generated_content)

        template_file = template_schema.get("template_file_path", "")
        docx_content = None
        if template_file:
            render_context = {
                **basic_info_snapshot,
                **(doc_content if isinstance(doc_content, dict) else {}),
            }
            docx_content = await render_template(template_file, render_context)

        latest_version = await self._get_latest_version(case_id, template_id, db)
        new_version = latest_version + 1

        template_name = template_schema.get("template_name", template_id)
        document_name = f"{template_name}-v{new_version}"

        upload_dir = getattr(settings, "UPLOAD_DIR", "./uploads")
        case_doc_dir = os.path.join(upload_dir, "cases", str(case_id), "documents")
        os.makedirs(case_doc_dir, exist_ok=True)

        md_filename = f"{case_id}_{template_id}_v{new_version}.md"
        docx_filename = f"{case_id}_{template_id}_v{new_version}.docx"
        md_path = os.path.join(case_doc_dir, md_filename)
        docx_path = os.path.join(case_doc_dir, docx_filename)

        with open(md_path, "w", encoding="utf-8") as f:
            f.write(content_str)

        if docx_content:
            with open(docx_path, "wb") as f:
                f.write(docx_content)

        parent_id = None
        if latest_version > 0:
            await cur.execute(
                "SELECT id FROM case_documents WHERE case_id = %s AND template_id = %s "
                "AND version = %s AND is_deleted = 0",
                (case_id, template_id, latest_version),
            )
            parent_row = await cur.fetchone()
            if parent_row:
                parent_id = parent_row["id"]

        await cur.execute(
            "INSERT INTO case_documents (case_id, template_id, template_name, document_name, "
            "version, parent_id, status, content_md_path, content_docx_path, "
            "basic_info, generated_content, generation_method, generation_prompt, created_by) "
            "VALUES (%s, %s, %s, %s, %s, %s, 'draft', %s, %s, %s, %s, 'ai_chat', %s, %s)",
            (
                case_id, template_id, template_name, document_name,
                new_version, parent_id, md_path, docx_path,
                json.dumps(basic_info_snapshot, ensure_ascii=False, default=str),
                json.dumps(doc_content, ensure_ascii=False, default=str) if isinstance(doc_content, dict) else json.dumps({"content": str(doc_content)}, ensure_ascii=False),
                generation_prompt, user_id,
            ),
        )
        doc_id = cur.lastrowid

        await cur.execute(
            "UPDATE cases SET document_count = document_count + 1, updated_at = NOW() WHERE id = %s",
            (case_id,),
        )

        try:
            await case_memory_service.create_or_update_case_memory(
                case_id, user_id, db
            )
        except Exception as e:
            logger.warning(f"Failed to update case memory after document generation: {e}")

        return {
            "success": True,
            "data": {
                "document_id": doc_id,
                "template_name": template_name,
                "document_name": document_name,
                "version": new_version,
                "status": "draft",
            },
        }

    async def _load_template_schema(self, template_id: str, db) -> Optional[dict]:
        conn, cur = db
        try:
            tid = int(template_id)
            await cur.execute(
                "SELECT id, template_code, template_name, template_category, template_file_path, "
                "schema_json FROM document_templates WHERE id = %s AND is_deleted = 0",
                (tid,),
            )
        except (ValueError, TypeError):
            await cur.execute(
                "SELECT id, template_code, template_name, template_category, template_file_path, "
                "schema_json FROM document_templates WHERE template_code = %s AND is_deleted = 0",
                (template_id,),
            )
        row = await cur.fetchone()
        if not row:
            return None
        result = dict(row)
        if result.get("schema_json") and isinstance(result["schema_json"], str):
            try:
                result["schema_json"] = json.loads(result["schema_json"])
            except (json.JSONDecodeError, TypeError):
                pass
        return result

    async def _get_latest_version(self, case_id: str, template_id: str, db) -> int:
        conn, cur = db
        await cur.execute(
            "SELECT MAX(version) as max_ver FROM case_documents "
            "WHERE case_id = %s AND template_id = %s AND is_deleted = 0",
            (case_id, template_id),
        )
        row = await cur.fetchone()
        return row["max_ver"] if row and row["max_ver"] else 0

    def _build_generation_prompt(self, template_schema: dict, info_pool: dict,
                                  conversation_context: dict = None) -> str:
        template_name = template_schema.get("template_name", "")
        schema = template_schema.get("schema_json", {})
        if isinstance(schema, str):
            try:
                schema = json.loads(schema)
            except (json.JSONDecodeError, TypeError):
                schema = {}

        context_section = ("\n## 对话上下文（用户补充信息）\n" + conversation_context.get('summary', '')) if conversation_context else ""

        basic_info_json = json.dumps(info_pool.get('basic_info', {}), ensure_ascii=False, indent=2)
        party_info_json = json.dumps(info_pool.get('party_info', {}), ensure_ascii=False, indent=2)
        officer_info_json = json.dumps(info_pool.get('officer_info', {}), ensure_ascii=False, indent=2)
        schema_json = json.dumps(schema, ensure_ascii=False, indent=2)
        illegal_fact_summary = info_pool.get('illegal_fact', {}).get('summary', '待补充')

        return f"""你是一个专业的市场监管执法文书生成助手。

## 任务
为当前案件生成"{template_name}"。

## 案件基本信息（已从信息池自动填充）
```json
{basic_info_json}
```

## 当事人信息
```json
{party_info_json}
```

## 执法人员信息
```json
{officer_info_json}
```

## 违法事实
{illegal_fact_summary}

## 文书结构要求（必须严格遵守以下Schema）
```json
{schema_json}
```

## 输出要求
请严格按照上述Schema结构生成JSON，确保：
1. 所有必填字段都已填充
2. 法条引用准确无误
3. 金额计算正确
4. 论述逻辑清晰完整
5. 语言符合执法文书规范
{context_section}

请直接输出JSON，不要添加其他说明文字。"""


document_generation_service = DocumentGenerationService()
