import json
import time
import logging
from typing import Optional

from .config import settings
from .llm_client import llm_client

COMPRESSION_PREFIX = "bff:compression:"
SUMMARY_PREFIX = "bff:summary:"

DEFAULT_TRIGGER_ROUNDS = 10
DEFAULT_TRIGGER_TOKENS = 8000
DEFAULT_TRIGGER_WINDOW_RATIO = 0.6
DEFAULT_COMPRESSION_MODEL = "glm-4-flash"

# 内存缓存（替代 Redis）
_summary_cache: dict = {}
_compression_done_cache: dict = {}

logger = logging.getLogger(__name__)


async def _get_compression_config() -> dict:
    """获取压缩配置（直接返回默认值，不再依赖 Redis/MySQL）"""
    return {
        "trigger_rounds": DEFAULT_TRIGGER_ROUNDS,
        "trigger_tokens": DEFAULT_TRIGGER_TOKENS,
        "trigger_window_ratio": DEFAULT_TRIGGER_WINDOW_RATIO,
        "model": DEFAULT_COMPRESSION_MODEL,
    }


async def should_compress(thread_id: str, messages: list, model_context_window: int = 128000) -> bool:
    config = await _get_compression_config()

    round_count = len([m for m in messages if m.get("role") == "user"])

    total_chars = sum(len(m.get("content", "")) for m in messages)
    estimated_tokens = total_chars // 2

    window_ratio = estimated_tokens / model_context_window if model_context_window > 0 else 0

    if thread_id in _compression_done_cache:
        return False

    if round_count >= config["trigger_rounds"]:
        return True
    if estimated_tokens >= config["trigger_tokens"]:
        return True
    if window_ratio >= config["trigger_window_ratio"]:
        return True

    return False


async def compress_context(thread_id: str, user_id: str = "", messages: list = None, db=None) -> Optional[str]:
    if messages is None:
        messages = []

    config = await _get_compression_config()

    conversation_messages = [m for m in messages if m.get("role") in ("user", "assistant")]
    conversation_text = "\n".join(
        [f"{'用户' if m['role'] == 'user' else 'AI'}: {m.get('content', '')}"
         for m in conversation_messages[-20:]]
    )

    prompt = f"""请对以下对话历史进行摘要压缩。保留关键信息、法律依据、事实认定和决策要点。摘要应简洁但完整，便于后续对话继续。

对话历史：
{conversation_text}

请生成结构化摘要："""

    summary = await _call_llm_for_summary(config["model"], prompt)

    if not summary:
        return None

    summary_data = {
        "thread_id": thread_id,
        "summary": summary,
        "original_message_count": len(conversation_messages),
        "compressed_at": time.time(),
        "model": config["model"],
    }

    # 内存缓存替代 Redis
    _summary_cache[thread_id] = summary_data
    _compression_done_cache[thread_id] = True

    return summary


async def _call_llm_for_summary(model: str, prompt: str, db=None) -> Optional[str]:
    """使用 llm_client.chat() 统一调用 LLM"""
    messages = [
        {"role": "system", "content": "你是一个专业的对话摘要助手。请用简洁的结构化格式输出摘要。"},
        {"role": "user", "content": prompt},
    ]

    result = await llm_client.chat(
        messages=messages,
        scene_key="chat_model",
        model=model,
        max_tokens=2048,
        temperature=0.1,
        timeout=30.0,
    )

    if result is not None:
        return result.strip()

    logger.warning("LLM 摘要调用失败，回退到本地摘要")
    return _local_summary(prompt)


def _local_summary(prompt: str) -> str:
    lines = prompt.split("\n")
    conversation_lines = [l for l in lines if l.startswith("[")]
    return f"[系统自动压缩] 对话共 {len(conversation_lines)} 条消息，已压缩为摘要。请基于此摘要继续对话。"


async def get_compressed_context(thread_id: str) -> Optional[dict]:
    """从内存缓存获取压缩摘要"""
    cached = _summary_cache.get(thread_id)
    if cached:
        return cached
    return None


async def build_messages_with_compression(thread_id: str, original_messages: list, new_user_message: str) -> list:
    compressed = await get_compressed_context(thread_id)

    if compressed:
        system_messages = [m for m in original_messages if m.get("role") == "system"]
        summary_msg = {
            "role": "system",
            "content": f"[对话历史摘要]\n{compressed['summary']}\n\n[以上为历史对话压缩摘要，请基于此继续对话]",
        }
        recent_messages = original_messages[-4:] if len(original_messages) > 4 else original_messages
        recent_messages = [m for m in recent_messages if m.get("role") != "system"]

        return system_messages + [summary_msg] + recent_messages + [{"role": "user", "content": new_user_message}]

    should = await should_compress(thread_id, original_messages)
    if should:
        summary = await compress_context(thread_id, messages=original_messages)
        if summary:
            system_messages = [m for m in original_messages if m.get("role") == "system"]
            summary_msg = {
                "role": "system",
                "content": f"[对话历史摘要]\n{summary}\n\n[以上为历史对话压缩摘要，请基于此继续对话]",
            }
            recent_messages = original_messages[-4:] if len(original_messages) > 4 else original_messages
            recent_messages = [m for m in recent_messages if m.get("role") != "system"]

            return system_messages + [summary_msg] + recent_messages + [{"role": "user", "content": new_user_message}]

    return original_messages + [{"role": "user", "content": new_user_message}]


async def invalidate_compression_cache(thread_id: str):
    """清除内存缓存"""
    _summary_cache.pop(thread_id, None)
    _compression_done_cache.pop(thread_id, None)
