import json
import logging
from datetime import date, datetime, timedelta
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.todo import DailyTodo, TodoSource
from app.models.task import Task, TaskStatus
from app.models.conversation import Conversation, Message
from app.services.llm_service import get_llm
from langchain_core.messages import HumanMessage, SystemMessage

logger = logging.getLogger(__name__)


async def generate_daily_todos(user_id: str, db: AsyncSession) -> list[DailyTodo]:
    """
    为用户生成今日待办：
    1. 来自前一天未完成的看板任务（最多20条）
    2. 来自前一天对话记录分析（最多3条）
    """
    today = date.today()
    yesterday = (today - timedelta(days=1)).isoformat()

    todos: list[DailyTodo] = []

    # 1. 从看板任务导入
    kanban_todos = await _import_kanban_tasks(user_id, yesterday, db)
    todos.extend(kanban_todos)

    # 2. 从对话记录分析
    chat_todos = await _analyze_chat_history(user_id, yesterday, db)
    todos.extend(chat_todos)

    return todos


async def _import_kanban_tasks(user_id: str, date_str: str, db: AsyncSession) -> list[DailyTodo]:
    """导入前一天创建的、未完成的看板任务"""
    q = select(Task).where(
        Task.user_id == user_id,
        Task.status != TaskStatus.DONE,
    ).order_by(Task.created_at.desc()).limit(20)

    tasks = (await db.execute(q)).scalars().all()
    todos = []

    for task in tasks:
        todo = DailyTodo(
            user_id=user_id,
            title=task.title,
            source=TodoSource.AI_KANBAN,
            source_detail=f"看板：{task.title}",
            source_ref_id=task.id,
            todo_date=date.today().isoformat(),
        )
        db.add(todo)
        todos.append(todo)

    if todos:
        await db.commit()
        for todo in todos:
            await db.refresh(todo)

    return todos


async def _analyze_chat_history(user_id: str, date_str: str, db: AsyncSession) -> list[DailyTodo]:
    """分析前一天对话，提取待办事项"""
    try:
        # 查询前一天创建的对话
        conv_q = select(Conversation).where(
            Conversation.user_id == user_id,
        ).order_by(Conversation.created_at.desc()).limit(10)
        convs = (await db.execute(conv_q)).scalars().all()

        # 过滤出昨天的对话
        yesterday_convs = []
        for conv in convs:
            created = conv.created_at
            if hasattr(created, 'date'):
                created_date = created.date() if hasattr(created, 'date') else created
            else:
                created_date = datetime.fromisoformat(str(created)).date()

            if str(created_date) == date_str or (created + timedelta(hours=8)).strftime('%Y-%m-%d') == date_str:
                yesterday_convs.append(conv)

        if not yesterday_convs:
            return []

        # 收集消息内容（限制2000字）
        messages_content = []
        for conv in yesterday_convs:
            msg_q = select(Message).where(
                Message.conversation_id == conv.id
            ).order_by(Message.created_at.asc()).limit(50)
            msgs = (await db.execute(msg_q)).scalars().all()
            for msg in msgs:
                if msg.content:
                    messages_content.append(f"[{msg.role}]: {msg.content[:500]}")

        if not messages_content:
            return []

        full_text = "\n".join(messages_content)[:2000]

        # 调用 LLM 分析
        prompt = f"""你是一个任务规划助手。请分析以下对话记录，提取其中用户想要完成但尚未明确完成的事项。

要求：
- 最多提取 3 条
- 每条格式：{{"title": "事项描述（50字以内）", "reason": "来源说明（60字以内）"}}
- 只提取用户明确表达过需求但还未完成的事项
- 如果没有可提取的内容，返回空数组 []

对话记录：
{full_text}

返回 JSON 数组："""

        llm = get_llm()
        response = await llm.invoke([
            SystemMessage(content="你是一个任务规划助手。"),
            HumanMessage(content=prompt),
        ])
        content = response.content if hasattr(response, 'content') else str(response)

        # 尝试解析 JSON
        try:
            # 提取 JSON 数组
            start = content.find('[')
            end = content.rfind(']') + 1
            if start != -1 and end > start:
                items = json.loads(content[start:end])
            else:
                items = []
        except (json.JSONDecodeError, ValueError):
            logger.warning(f"LLM 返回格式异常，跳过对话分析: {content[:200]}")
            items = []

        if not items:
            return []

        todos = []
        for item in items[:3]:
            todo = DailyTodo(
                user_id=user_id,
                title=item.get("title", "")[:500],
                source=TodoSource.AI_CHAT,
                source_detail=f"对话：{item.get('reason', '')[:60]}",
                todo_date=date.today().isoformat(),
            )
            db.add(todo)
            todos.append(todo)

        if todos:
            await db.commit()
            for todo in todos:
                await db.refresh(todo)

        return todos

    except Exception as e:
        logger.error(f"对话分析失败: {e}")
        return []
