# -*- coding: utf-8 -*-
"""
备注回溯重分类器（Note Reclassifier）

召回完成后，回溯检查是否有普通备注需重分类为回访备注，并创建回访任务。

流程：
1. 查找 service_time 之后的第一条 normal 备注
2. 若找到 → 重分类为 follow_up，任务状态 = completed（回溯完成）
3. 若未找到 → 任务状态 = active（等待备注）
4. 冲突检查：已有 completed → 跳过；已有 active → 顶替；否则正常创建
5. 保留 ai_analyze_note() 占位调用，返回值仅更新 ai_score 字段

由 trigger_jobs 中的 note_reclassify_backfill 配置驱动（event: recall_completed）。
"""

import json
import logging

from app.trace.decorators import trace_service

logger = logging.getLogger(__name__)


def _get_connection():
    """延迟导入 get_connection，避免模块级导入失败。"""
    from app.database import get_connection

    return get_connection()


def _insert_history(
    cur,
    task_id: int,
    action: str,
    old_status: str | None = None,
    new_status: str | None = None,
    old_task_type: str | None = None,
    new_task_type: str | None = None,
    detail: dict | None = None,
) -> None:
    """在 coach_task_history 中记录变更。"""
    cur.execute(
        """
        INSERT INTO biz.coach_task_history
            (task_id, action, old_status, new_status,
             old_task_type, new_task_type, detail)
        VALUES (%s, %s, %s, %s, %s, %s, %s)
        """,
        (
            task_id,
            action,
            old_status,
            new_status,
            old_task_type,
            new_task_type,
            json.dumps(detail) if detail else None,
        ),
    )


@trace_service(description_zh="ai_analyze_note", description_en="Ai Analyze Note")
def ai_analyze_note(note_id: int) -> int | None:
    """
    AI 应用 6 备注分析接口（占位）。

    P5 AI 集成层实现后替换此占位函数。
    当前返回 None 表示 AI 未就绪，跳过评分逻辑。
    """
    return None


@trace_service(description_zh="执行笔记重分类", description_en="Run note reclassification")
def run(payload: dict | None = None, job_id: int | None = None) -> dict:
    """
    备注回溯主流程。

    payload 包含: {site_id, assistant_id, member_id, service_time}

    流程：
    1. 查找 service_time 之后的第一条 normal 备注 → note_id
    2. 若 note_id 存在：重分类为 follow_up，task_status = 'completed'（回溯完成）
    3. 若 note_id 不存在：task_status = 'active'（等待备注）
    4. 保留 ai_analyze_note() 占位调用，返回值仅更新 ai_score 字段
    5. 冲突检查（T3）：
       - 已有 completed → 跳过创建
       - 已有 active → 旧任务标记 inactive + superseded 历史，创建新任务
       - 不存在（或仅 inactive/abandoned）→ 正常创建
    6. 创建 follow_up_visit 任务

    参数:
        payload: 事件载荷（由 trigger_scheduler 传入）
        job_id: 触发器 job ID（由 trigger_scheduler 传入），用于在最终事务中
                更新 last_run_at，保证 handler 数据变更与 last_run_at 原子提交

    返回: {"reclassified_count": int, "tasks_created": int}
    """
    if not payload:
        return {"reclassified_count": 0, "tasks_created": 0}

    site_id = payload.get("site_id")
    assistant_id = payload.get("assistant_id")
    member_id = payload.get("member_id")
    service_time = payload.get("service_time")

    if not all([site_id, assistant_id, member_id, service_time]):
        logger.warning("备注回溯缺少必要参数: %s", payload)
        return {"reclassified_count": 0, "tasks_created": 0}

    reclassified_count = 0
    tasks_created = 0

    conn = _get_connection()
    try:
        # ── 1. 查找 service_time 之后的第一条 normal 备注 ──
        note_id = None
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT id
                FROM biz.notes
                WHERE site_id = %s
                  AND target_type = 'member'
                  AND target_id = %s
                  AND type = 'normal'
                  AND created_at > %s
                ORDER BY created_at ASC
                LIMIT 1
                """,
                (site_id, member_id, service_time),
            )
            row = cur.fetchone()
            if row:
                note_id = row[0]
        conn.commit()

        # ── 2. 根据是否找到备注确定任务状态（T4） ──
        if note_id is not None:
            # 找到备注 → 重分类为 follow_up
            with conn.cursor() as cur:
                cur.execute("BEGIN")
                cur.execute(
                    """
                    UPDATE biz.notes
                    SET type = 'follow_up', updated_at = NOW()
                    WHERE id = %s AND type = 'normal'
                    """,
                    (note_id,),
                )
            conn.commit()
            reclassified_count = 1

            # 保留 AI 占位调用，返回值仅用于更新 ai_score 字段
            ai_score = ai_analyze_note(note_id)
            if ai_score is not None:
                with conn.cursor() as cur:
                    cur.execute("BEGIN")
                    cur.execute(
                        """
                        UPDATE biz.notes
                        SET ai_score = %s, updated_at = NOW()
                        WHERE id = %s
                        """,
                        (ai_score, note_id),
                    )
                conn.commit()

            # 有备注 → 回溯完成
            task_status = "completed"
        else:
            # 未找到备注 → 等待备注
            logger.info(
                "未找到符合条件的 normal 备注: site_id=%s, member_id=%s",
                site_id, member_id,
            )
            ai_score = None
            task_status = "active"

        # ── 3. 冲突检查（T3）：查询已有 follow_up_visit 任务 ──
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT id, status
                FROM biz.coach_tasks
                WHERE site_id = %s AND assistant_id = %s AND member_id = %s
                  AND task_type = 'follow_up_visit'
                  AND status IN ('active', 'completed')
                ORDER BY CASE WHEN status = 'completed' THEN 0 ELSE 1 END
                LIMIT 1
                """,
                (site_id, assistant_id, member_id),
            )
            existing = cur.fetchone()
        conn.commit()

        if existing:
            existing_id, existing_status = existing
            if existing_status == "completed":
                # 已完成 → 跳过创建（回访完成语义已满足）
                logger.info(
                    "已存在 completed 回访任务 id=%s，跳过创建: "
                    "site_id=%s, assistant_id=%s, member_id=%s",
                    existing_id, site_id, assistant_id, member_id,
                )
                # 事务安全（T5）：即使跳过创建，handler 仍成功，更新 last_run_at
                if job_id is not None:
                    from app.services.trigger_scheduler import (
                        update_job_last_run_at,
                    )

                    with conn.cursor() as cur:
                        cur.execute("BEGIN")
                        update_job_last_run_at(cur, job_id)
                    conn.commit()
                return {
                    "reclassified_count": reclassified_count,
                    "tasks_created": 0,
                }
            elif existing_status == "active":
                # 顶替：旧任务 → inactive + superseded 历史
                with conn.cursor() as cur:
                    cur.execute("BEGIN")
                    cur.execute(
                        """
                        UPDATE biz.coach_tasks
                        SET status = 'inactive', updated_at = NOW()
                        WHERE id = %s AND status = 'active'
                        """,
                        (existing_id,),
                    )
                    _insert_history(
                        cur,
                        existing_id,
                        action="superseded",
                        old_status="active",
                        new_status="inactive",
                        detail={
                            "reason": "new_reclassify_task_supersedes",
                            "source": "note_reclassifier",
                        },
                    )
                conn.commit()
                logger.info(
                    "顶替旧 active 回访任务 id=%s → inactive: "
                    "site_id=%s, assistant_id=%s, member_id=%s",
                    existing_id, site_id, assistant_id, member_id,
                )

        # ── 4. 创建 follow_up_visit 任务 ──
        with conn.cursor() as cur:
            cur.execute("BEGIN")
            cur.execute(
                """
                INSERT INTO biz.coach_tasks
                    (site_id, assistant_id, member_id, task_type,
                     status, completed_at, completed_task_type)
                VALUES (
                    %s, %s, %s, 'follow_up_visit',
                    %s,
                    CASE WHEN %s = 'completed' THEN NOW() ELSE NULL END,
                    CASE WHEN %s = 'completed' THEN 'follow_up_visit' ELSE NULL END
                )
                RETURNING id
                """,
                (
                    site_id, assistant_id, member_id,
                    task_status, task_status, task_status,
                ),
            )
            new_task_row = cur.fetchone()
            new_task_id = new_task_row[0]

            # 记录任务创建历史
            _insert_history(
                cur,
                new_task_id,
                action="created_by_reclassify",
                old_status=None,
                new_status=task_status,
                old_task_type=None,
                new_task_type="follow_up_visit",
                detail={
                    "note_id": note_id,
                    "ai_score": ai_score,
                    "source": "note_reclassifier",
                },
            )

            # 事务安全（T5）：在最终 commit 前更新 last_run_at
            if job_id is not None:
                from app.services.trigger_scheduler import update_job_last_run_at

                update_job_last_run_at(cur, job_id)

        conn.commit()
        tasks_created = 1

    except Exception:
        logger.exception(
            "备注回溯失败: site_id=%s, member_id=%s",
            site_id, member_id,
        )
        conn.rollback()
    finally:
        conn.close()

    logger.info(
        "备注回溯完成: reclassified_count=%d, tasks_created=%d",
        reclassified_count, tasks_created,
    )
    return {
        "reclassified_count": reclassified_count,
        "tasks_created": tasks_created,
    }

