"""
说话人服务 - 处理说话人识别和管理相关功能
"""
import re
import logging
from datetime import datetime

from flask import current_app
from flask_login import current_user

from src.clients import db
from src.models import Speaker, SystemSetting
from src.services.llm_service import call_llm_completion, format_transcription_for_llm
from src.utils.json_utils import safe_json_loads

logger = logging.getLogger(__name__)


def update_speaker_usage(speaker_names):
    """
    更新说话人使用统计
    
    Args:
        speaker_names: 说话人名称列表
    """
    if not speaker_names or not current_user.is_authenticated:
        return
    
    try:
        for name in speaker_names:
            name = name.strip()
            if not name:
                continue
                
            speaker = Speaker.query.filter_by(user_id=current_user.id, name=name).first()
            if speaker:
                # 更新现有说话人
                speaker.use_count += 1
                speaker.last_used = datetime.utcnow()
            else:
                # 创建新说话人
                speaker = Speaker(
                    name=name,
                    user_id=current_user.id,
                    use_count=1,
                    created_at=datetime.utcnow(),
                    last_used=datetime.utcnow()
                )
                db.session.add(speaker)
        
        db.session.commit()
    except Exception as e:
        current_app.logger.error(f"更新说话人使用统计时出错: {e}")
        db.session.rollback()


def identify_speakers_from_text(transcription):
    """
    使用 LLM 从转录文本中识别说话人
    
    Args:
        transcription: 转录文本(可能是 JSON 格式)
    
    Returns:
        dict: 说话人标签到名称的映射,如 {"SPEAKER_00": "张三", "SPEAKER_01": "李四"}
    
    Raises:
        ValueError: 如果 TEXT_MODEL_API_KEY 未配置
    """
    from src.config import TEXT_MODEL_API_KEY
    
    if not TEXT_MODEL_API_KEY:
        raise ValueError("TEXT_MODEL_API_KEY 未配置。")

    # 转录文本可能是 JSON,先格式化
    formatted_transcription = format_transcription_for_llm(transcription)

    # 提取现有的说话人标签(如 SPEAKER_00, SPEAKER_01),按出现顺序
    all_labels = re.findall(r'\[(SPEAKER_\d+)\]', formatted_transcription)
    seen = set()
    speaker_labels = [x for x in all_labels if not (x in seen or seen.add(x))]
    
    if not speaker_labels:
        return {}

    # 获取可配置的转录文本长度限制
    transcript_limit = SystemSetting.get_setting('transcript_length_limit', 30000)
    if transcript_limit == -1:
        # 不限制
        transcript_text = formatted_transcription
    else:
        transcript_text = formatted_transcription[:transcript_limit]

    prompt = f"""分析以下转录文本并识别说话人的姓名。说话人被标记为 {', '.join(speaker_labels)}。根据对话上下文,确定每个说话人标签最可能的姓名。

转录文本:
---
{transcript_text}
---

回复一个 JSON 对象,键是说话人标签(如 "SPEAKER_00"),值是识别出的全名。如果无法确定姓名,使用值 "Unknown"。

示例:
{{
  "SPEAKER_00": "张三",
  "SPEAKER_01": "李四",
  "SPEAKER_02": "Unknown"
}}

JSON 响应:
"""

    try:
        completion = call_llm_completion(
            messages=[
                {"role": "system", "content": "你是分析对话转录文本以识别说话人的专家。你的回复必须是单个、有效的 JSON 对象。"},
                {"role": "user", "content": prompt}
            ],
            temperature=0.2,
            response_format={"type": "json_object"}
        )
        response_content = completion.choices[0].message.content
        speaker_map = safe_json_loads(response_content, {})

        # 后处理:将 "Unknown" 替换为空字符串
        for speaker_label, identified_name in speaker_map.items():
            if identified_name.strip().lower() == "unknown":
                speaker_map[speaker_label] = ""
                
        return speaker_map
    except Exception as e:
        current_app.logger.error(f"调用 LLM 识别说话人时出错: {e}")
        raise


def identify_unidentified_speakers_from_text(transcription, unidentified_speakers):
    """
    使用 LLM 仅识别转录文本中未识别的说话人
    
    Args:
        transcription: 转录文本(可能是 JSON 格式)
        unidentified_speakers: 需要识别的说话人标签列表
    
    Returns:
        dict: 说话人标签到名称的映射
    
    Raises:
        ValueError: 如果 TEXT_MODEL_API_KEY 未配置
    """
    from src.config import TEXT_MODEL_API_KEY
    
    if not TEXT_MODEL_API_KEY:
        raise ValueError("TEXT_MODEL_API_KEY 未配置。")

    # 转录文本可能是 JSON,先格式化
    formatted_transcription = format_transcription_for_llm(transcription)

    if not unidentified_speakers:
        return {}

    # 获取可配置的转录文本长度限制
    transcript_limit = SystemSetting.get_setting('transcript_length_limit', 30000)
    if transcript_limit == -1:
        # 不限制
        transcript_text = formatted_transcription
    else:
        transcript_text = formatted_transcription[:transcript_limit]

    prompt = f"""分析以下对话转录文本,根据对话的上下文和内容识别未识别说话人的姓名。

需要识别的说话人是: {', '.join(unidentified_speakers)}

在对话中寻找线索,如:
- 其他说话人在称呼某人时提到的名字
- 自我介绍或提及自己姓名
- 关于角色、关系或职位的上下文线索
- 对话中直接提到的姓名

以下是完整的对话转录文本:

{transcript_text}

根据以上对话,识别未识别说话人最可能的真实姓名。注意倾听说话人之间如何称呼对方以及对话中提到的姓名。

回复一个 JSON 对象,键是说话人标签(如 "SPEAKER_01"),值是识别出的全名。如果无法从对话上下文中确定姓名,使用空字符串 ""。

示例格式:
{{
  "SPEAKER_01": "张三",
  "SPEAKER_03": "李四",
  "SPEAKER_05": ""
}}

JSON 响应:
"""

    try:
        completion = call_llm_completion(
            messages=[
                {"role": "system", "content": "你是根据对话上下文线索分析对话转录文本以识别说话人的专家。仔细分析对话,找出说话人相互称呼时提到的名字或自我介绍时的姓名。你的回复必须是单个、有效的 JSON 对象,仅包含请求的说话人识别信息。"},
                {"role": "user", "content": prompt}
            ],
            temperature=0.2,
            response_format={"type": "json_object"}
        )
        response_content = completion.choices[0].message.content
        speaker_map = safe_json_loads(response_content, {})

        # 后处理:将 "Unknown" 等替换为空字符串
        for speaker_label, identified_name in speaker_map.items():
            if identified_name and identified_name.strip().lower() in ["unknown", "n/a", "not available", "unclear"]:
                speaker_map[speaker_label] = ""
                
        return speaker_map
    except Exception as e:
        current_app.logger.error(f"调用 LLM 识别说话人时出错: {e}")
        raise
