import uuid
import logging
from typing import Optional

from ..core.llm_client import llm_client

logger = logging.getLogger(__name__)

SUMMARY_TRIGGER_ROUNDS = 6
SUMMARY_KEEP_RECENT = 4
SUMMARY_MAX_TOKENS = 512


async def get_thread_summary(thread_id: str, db) -> Optional[str]:
    conn, cur = db
    try:
        await cur.execute(
            "SELECT summary_text, covered_msg_count FROM chat_summaries WHERE thread_id = %s ORDER BY updated_at DESC LIMIT 1",
            (thread_id,),
        )
        row = await cur.fetchone()
        if row:
            return row.get("summary_text") if isinstance(row, dict) else row[0]
        return None
    except Exception as e:
        logger.warning(f"Failed to get thread summary: {e}")
        return None


async def should_generate_summary(thread_id: str, db) -> bool:
    conn, cur = db
    try:
        await cur.execute(
            "SELECT COUNT(*) as cnt FROM chat_messages WHERE thread_id = %s AND role IN ('user', 'assistant') AND content != ''",
            (thread_id,),
        )
        row = await cur.fetchone()
        total_msgs = row.get("cnt", 0) if isinstance(row, dict) else row[0]

        await cur.execute(
            "SELECT covered_msg_count FROM chat_summaries WHERE thread_id = %s ORDER BY updated_at DESC LIMIT 1",
            (thread_id,),
        )
        sum_row = await cur.fetchone()
        covered = sum_row.get("covered_msg_count", 0) if isinstance(sum_row, dict) else (sum_row[0] if sum_row else 0)

        uncovered = total_msgs - covered
        return uncovered >= SUMMARY_TRIGGER_ROUNDS * 2
    except Exception as e:
        logger.warning(f"Failed to check summary need: {e}")
        return False


async def generate_and_save_summary(thread_id: str, db) -> Optional[str]:
    conn, cur = db
    try:
        await cur.execute(
            "SELECT covered_msg_count FROM chat_summaries WHERE thread_id = %s ORDER BY updated_at DESC LIMIT 1",
            (thread_id,),
        )
        sum_row = await cur.fetchone()
        covered_count = sum_row.get("covered_msg_count", 0) if isinstance(sum_row, dict) else (sum_row[0] if sum_row else 0)
        existing_summary = None
        if sum_row:
            await cur.execute(
                "SELECT summary_text FROM chat_summaries WHERE thread_id = %s ORDER BY updated_at DESC LIMIT 1",
                (thread_id,),
            )
            s_row = await cur.fetchone()
            existing_summary = s_row.get("summary_text", "") if isinstance(s_row, dict) else (s_row[0] if s_row else "")

        skip_count = covered_count
        keep_recent = SUMMARY_KEEP_RECENT * 2

        await cur.execute(
            "SELECT COUNT(*) as cnt FROM chat_messages WHERE thread_id = %s AND role IN ('user', 'assistant') AND content != ''",
            (thread_id,),
        )
        total_row = await cur.fetchone()
        total_msgs = total_row.get("cnt", 0) if isinstance(total_row, dict) else total_row[0]

        msgs_to_summarize = total_msgs - skip_count - keep_recent
        if msgs_to_summarize < 2:
            return existing_summary

        await cur.execute(
            "SELECT role, content, ocr_content FROM chat_messages "
            "WHERE thread_id = %s AND role IN ('user', 'assistant') AND content != '' "
            "ORDER BY created_at ASC LIMIT %s OFFSET %s",
            (thread_id, msgs_to_summarize, skip_count),
        )
        rows = await cur.fetchall()

        if not rows:
            return existing_summary

        conversation_text = ""
        msg_ids = []
        for r in rows:
            role = r.get("role", "")
            content = r.get("content", "")
            ocr = r.get("ocr_content") or ""
            label = "用户" if role == "user" else "助手"
            if ocr and len(ocr) > 300:
                ocr = ocr[:300] + "..."
            display = content if len(content) <= 300 else content[:300] + "..."
            if ocr and role == "user":
                display += f"\n[附件内容]: {ocr}"
            conversation_text += f"{label}: {display}\n\n"

        summary = await _call_llm_for_summary(conversation_text, existing_summary)
        if not summary:
            return existing_summary

        new_covered = covered_count + len(rows)

        await cur.execute(
            "SELECT id FROM chat_summaries WHERE thread_id = %s ORDER BY updated_at DESC LIMIT 1",
            (thread_id,),
        )
        existing = await cur.fetchone()
        if existing:
            existing_id = existing.get("id") if isinstance(existing, dict) else existing[0]
            await cur.execute(
                "UPDATE chat_summaries SET summary_text = %s, covered_msg_count = %s, updated_at = NOW() WHERE id = %s",
                (summary, new_covered, existing_id),
            )
        else:
            await cur.execute(
                "INSERT INTO chat_summaries (id, thread_id, summary_text, covered_msg_count, created_at, updated_at) "
                "VALUES (%s, %s, %s, %s, NOW(), NOW())",
                (str(uuid.uuid4()), thread_id, summary, new_covered),
            )
        await conn.commit()
        logger.info(f"Summary saved for thread {thread_id}: covered={new_covered}, len={len(summary)}")
        return summary

    except Exception as e:
        logger.error(f"Failed to generate summary: {e}", exc_info=True)
        return None


async def _call_llm_for_summary(conversation_text: str, existing_summary: Optional[str]) -> Optional[str]:
    try:
        system_prompt = (
            "你是一个对话摘要助手。请将以下对话历史压缩为一段简洁的摘要，保留关键信息：\n"
            "1. 讨论的主要话题和问题\n"
            "2. 涉及的具体案件、法规、文书等关键实体\n"
            "3. 用户的核心诉求和AI给出的关键结论\n"
            "4. 附件中识别出的重要内容\n\n"
            "要求：摘要不超过300字，只保留对后续对话有价值的信息，删除冗余和重复。"
        )

        if existing_summary:
            user_prompt = f"已有摘要：\n{existing_summary}\n\n新增对话：\n{conversation_text}\n\n请将已有摘要和新增对话合并为一段更新后的摘要："
        else:
            user_prompt = f"请为以下对话生成摘要：\n{conversation_text}"

        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ]

        summary = await llm_client.chat(
            messages=messages,
            scene_key="chat_model",
            max_tokens=SUMMARY_MAX_TOKENS,
            temperature=0.3,
            timeout=30.0,
        )
        return summary

    except Exception as e:
        logger.error(f"LLM summary call failed: {e}")
        return None
