"""
优化建议引擎 - 基于品牌数据差距提供可操作的优化建议

建议类型:
- content_optimization: 内容优化建议（如何让AI更容易引用你的内容）
- platform_targeting: 平台定向建议（哪些平台需要重点优化）
- competitor_gap: 竞品差距建议（如何缩小与竞品的差距）
- query_expansion: 查询词扩展建议（应该添加哪些查询词）
- citation_improvement: 引用改善建议（如何增加被引用的概率）

生成逻辑:
1. 基于评分V2的五维度数据，找出最弱的维度
2. 基于竞品对比数据，找出差距最大的方面
3. 基于情感分析数据，找出负面情感的来源
4. 使用DeepSeek API生成个性化建议（ENABLE_LLM控制开关）
5. 无LLM时使用基于规则的模板建议
"""
from __future__ import annotations

import asyncio
import json
import logging
import uuid
from dataclasses import dataclass, field
from typing import Any

from app.config import settings
from app.services.scoring_service import ScoringResultV2

logger = logging.getLogger(__name__)


# ============================================================
# 建议数据结构
# ============================================================

@dataclass
class SuggestionItem:
    """单条优化建议"""
    type: str           # content_optimization/platform_targeting/competitor_gap/query_expansion/citation_improvement
    priority: str       # high/medium/low
    title: str          # 建议标题
    description: str    # 详细描述
    action: str         # 具体操作步骤
    expected_impact: str  # 预期效果
    difficulty: str     # easy/medium/hard


@dataclass
class BrandAnalysisContext:
    """品牌分析上下文 - 用于生成建议的输入数据"""
    brand_name: str
    overall_score: float
    # 五维度评分
    mention_rate_score: float = 0.0
    mention_rate_max: float = 25.0
    mention_rate_percentage: float = 0.0
    rank_score: float = 0.0
    rank_max: float = 25.0
    rank_percentage: float = 0.0
    sentiment_score: float = 0.0
    sentiment_max: float = 20.0
    sentiment_percentage: float = 0.0
    citation_score: float = 0.0
    citation_max: float = 15.0
    citation_percentage: float = 0.0
    competitive_score: float = 0.0
    competitive_max: float = 15.0
    competitive_percentage: float = 0.0
    # 竞品对比数据
    competitor_data: dict[str, Any] = field(default_factory=dict)
    # 情感分析数据
    sentiment_data: dict[str, int] = field(default_factory=dict)
    # 平台评分数据
    platform_scores: dict[str, float] = field(default_factory=dict)
    # 查询词数据
    total_queries: int = 0
    mentioned_count: int = 0


# ============================================================
# 基于规则的建议生成器
# ============================================================

def _get_weakest_dimensions(ctx: BrandAnalysisContext) -> list[tuple[str, float, float]]:
    """
    找出最弱的维度，按得分率升序排列。

    Returns:
        [(维度名, 得分率, 得分), ...]
    """
    dimensions = [
        ("提及率", ctx.mention_rate_percentage, ctx.mention_rate_score),
        ("推荐排名", ctx.rank_percentage, ctx.rank_score),
        ("情感倾向", ctx.sentiment_percentage, ctx.sentiment_score),
        ("引用质量", ctx.citation_percentage, ctx.citation_score),
        ("竞品对比", ctx.competitive_percentage, ctx.competitive_score),
    ]
    return sorted(dimensions, key=lambda x: x[1])


def _generate_content_optimization_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """生成内容优化建议"""
    suggestions: list[SuggestionItem] = []

    # 提及率低 -> 内容优化
    if ctx.mention_rate_percentage < 50:
        suggestions.append(SuggestionItem(
            type="content_optimization",
            priority="high",
            title="提升品牌内容在AI平台的可见性",
            description=(
                f"当前提及率仅{ctx.mention_rate_percentage:.0f}%，"
                f"品牌在AI回答中被提及的频率较低。"
                f"AI平台倾向于引用结构化、权威性强的内容。"
            ),
            action=(
                "1. 在官网和核心页面添加FAQ结构化数据(Schema.org FAQPage)\n"
                "2. 创建行业白皮书和深度分析文章，使用清晰的标题层级\n"
                "3. 确保品牌在维基百科、行业百科等权威来源有准确条目\n"
                "4. 优化内容中的品牌名称一致性，避免过多别名导致AI无法识别"
            ),
            expected_impact="预计可将提及率提升15-25个百分点",
            difficulty="medium",
        ))
    elif ctx.mention_rate_percentage < 75:
        suggestions.append(SuggestionItem(
            type="content_optimization",
            priority="medium",
            title="持续优化品牌内容结构",
            description=(
                f"当前提及率为{ctx.mention_rate_percentage:.0f}%，仍有提升空间。"
                f"建议进一步优化内容结构以提高AI引用概率。"
            ),
            action=(
                "1. 增加品牌相关的高质量长文内容（2000字以上）\n"
                "2. 在内容中增加数据支撑和案例引用\n"
                "3. 定期更新内容以保持时效性"
            ),
            expected_impact="预计可将提及率提升5-15个百分点",
            difficulty="easy",
        ))

    return suggestions


def _generate_platform_targeting_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """生成平台定向建议"""
    suggestions: list[SuggestionItem] = []

    # 找出评分最低的平台
    if ctx.platform_scores:
        weak_platforms = sorted(
            ctx.platform_scores.items(),
            key=lambda x: x[1],
        )[:3]
        weak_platform_names = [p[0] for p in weak_platforms if p[1] < 40]
        weak_platform_str = "、".join(weak_platform_names) if weak_platform_names else ""

        if weak_platform_str:
            suggestions.append(SuggestionItem(
                type="platform_targeting",
                priority="high",
                title=f"重点优化{weak_platform_str}平台表现",
                description=(
                    f"在这些平台上品牌评分低于40分，"
                    f"AI引用率极低。不同AI平台有不同的内容偏好，"
                    f"需要针对性优化。"
                ),
                action=(
                    f"1. 分析{weak_platform_str}平台的内容偏好和引用模式\n"
                    "2. 针对各平台优化内容格式和表达方式\n"
                    "3. 增加在这些平台关联的内容源数量\n"
                    "4. 关注平台算法更新，及时调整优化策略"
                ),
                expected_impact="预计可将弱平台评分提升20-30分",
                difficulty="hard",
            ))

    # 如果没有平台数据
    if not ctx.platform_scores or all(v == 0 for v in ctx.platform_scores.values()):
        suggestions.append(SuggestionItem(
            type="platform_targeting",
            priority="high",
            title="启动全平台品牌监控",
            description=(
                "当前没有任何平台的引用数据。"
                "需要先在各AI平台建立品牌存在感。"
            ),
            action=(
                "1. 确保已添加足够的查询词覆盖核心业务关键词\n"
                "2. 等待系统完成首轮数据采集（通常需要1-2天）\n"
                "3. 采集完成后查看各平台评分，确定优先优化方向"
            ),
            expected_impact="获取全平台基准数据，为后续优化提供方向",
            difficulty="easy",
        ))

    return suggestions


def _generate_competitor_gap_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """生成竞品差距建议"""
    suggestions: list[SuggestionItem] = []

    # 竞品对比维度弱
    if ctx.competitive_percentage < 40:
        # 找出领先的品牌
        ahead_competitors = []
        behind_competitors = []
        if ctx.competitor_data:
            brand_mentions = ctx.competitor_data.get("brand_mentions", 0)
            for name, count in ctx.competitor_data.get("competitor_mentions", {}).items():
                if count > brand_mentions:
                    ahead_competitors.append((name, count))
                else:
                    behind_competitors.append((name, count))

        ahead_str = "、".join([n for n, _ in ahead_competitors[:3]]) if ahead_competitors else "竞品"

        suggestions.append(SuggestionItem(
            type="competitor_gap",
            priority="high",
            title=f"缩小与{ahead_str}的差距",
            description=(
                f"当前竞品对比得分率仅{ctx.competitive_percentage:.0f}%，"
                f"品牌在AI引用中落后于主要竞品。"
                f"需要分析竞品的优势领域并制定追赶策略。"
            ),
            action=(
                "1. 分析竞品在AI平台被引用的内容类型和话题\n"
                "2. 找出竞品有而品牌缺失的内容领域\n"
                "3. 针对性创建竞品优势领域的优质内容\n"
                "4. 加强品牌差异化定位，突出独特价值主张"
            ),
            expected_impact="预计3-6个月内可将竞品对比得分率提升15-25个百分点",
            difficulty="hard",
        ))
    elif ctx.competitive_percentage < 70:
        suggestions.append(SuggestionItem(
            type="competitor_gap",
            priority="medium",
            title="持续巩固竞争优势",
            description=(
                f"当前竞品对比得分率为{ctx.competitive_percentage:.0f}%，"
                f"品牌处于中等水平，需要持续巩固并扩大优势。"
            ),
            action=(
                "1. 定期监控竞品动态和内容更新\n"
                "2. 在品牌优势领域持续输出高质量内容\n"
                "3. 关注新兴话题和趋势，抢占先机"
            ),
            expected_impact="预计可将竞品对比得分率提升10-15个百分点",
            difficulty="medium",
        ))

    return suggestions


def _generate_query_expansion_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """生成查询词扩展建议"""
    suggestions: list[SuggestionItem] = []

    # 查询词数量不足
    if ctx.total_queries < 10:
        suggestions.append(SuggestionItem(
            type="query_expansion",
            priority="high" if ctx.total_queries < 3 else "medium",
            title="扩展查询词覆盖范围",
            description=(
                f"当前仅有{ctx.total_queries}个查询词，"
                f"覆盖范围不足，无法全面反映品牌在AI搜索中的表现。"
                f"更多查询词意味着更全面的品牌认知度画像。"
            ),
            action=(
                "1. 添加行业核心关键词（如：'XX行业推荐'、'XX解决方案'）\n"
                "2. 添加品牌相关长尾词（如：'XX品牌怎么样'、'XX vs 竞品'）\n"
                "3. 添加场景化查询词（如：'XX场景下选什么产品'）\n"
                "4. 建议至少添加10-20个查询词以获得可靠的分析结果"
            ),
            expected_impact="更多查询词可提升评分准确度，发现更多优化机会",
            difficulty="easy",
        ))

    # 提及率低且查询词不少 -> 可能需要优化查询词质量
    elif ctx.total_queries >= 10 and ctx.mention_rate_percentage < 50:
        suggestions.append(SuggestionItem(
            type="query_expansion",
            priority="medium",
            title="优化查询词质量和相关性",
            description=(
                f"已有{ctx.total_queries}个查询词，但提及率仅{ctx.mention_rate_percentage:.0f}%。"
                f"可能是查询词与品牌核心业务关联度不够。"
            ),
            action=(
                "1. 检查现有查询词是否覆盖品牌核心业务场景\n"
                "2. 添加品牌擅长的专业领域相关查询词\n"
                "3. 删除与品牌无关的宽泛查询词\n"
                "4. 增加品牌独特卖点和差异化优势相关的查询词"
            ),
            expected_impact="优化查询词后可提升提及率10-20个百分点",
            difficulty="easy",
        ))

    return suggestions


def _generate_citation_improvement_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """生成引用改善建议"""
    suggestions: list[SuggestionItem] = []

    # 引用质量低
    if ctx.citation_percentage < 40:
        suggestions.append(SuggestionItem(
            type="citation_improvement",
            priority="high",
            title="提升AI引用内容的质量和深度",
            description=(
                f"当前引用质量得分率仅{ctx.citation_percentage:.0f}%，"
                f"AI对品牌的引用多为浅层提及，缺乏深度正面描述。"
                f"高质量引用能显著影响用户决策。"
            ),
            action=(
                "1. 创建详细的产品对比页面，包含数据表格和评测结论\n"
                "2. 发布客户案例和成功故事，提供具体数据支撑\n"
                "3. 在内容中增加可引用的数据点和统计信息\n"
                "4. 优化内容结构，使用AI易于提取的格式（列表、表格、要点）"
            ),
            expected_impact="预计可将引用质量得分率提升15-25个百分点",
            difficulty="medium",
        ))

    # 推荐排名低
    if ctx.rank_percentage < 40:
        suggestions.append(SuggestionItem(
            type="citation_improvement",
            priority="high",
            title="提升品牌在AI推荐中的排名位置",
            description=(
                f"当前推荐排名得分率仅{ctx.rank_percentage:.0f}%，"
                f"品牌在AI推荐列表中排名靠后，用户看到概率低。"
                f"排名越靠前，被用户选择的可能性越大。"
            ),
            action=(
                "1. 增加品牌在权威第三方平台的正面评价和推荐\n"
                "2. 优化品牌在行业榜单和评测中的排名\n"
                "3. 创建'最佳XX'、'XX推荐'类内容，增加被推荐概率\n"
                "4. 提升品牌官网的SEO表现，增加AI爬取到的概率"
            ),
            expected_impact="预计可将推荐排名提升2-3位",
            difficulty="medium",
        ))

    # 情感倾向差
    negative_rate = 0.0
    total_sentiment = sum(ctx.sentiment_data.values())
    if total_sentiment > 0:
        negative_rate = ctx.sentiment_data.get("negative", 0) / total_sentiment

    if negative_rate > 0.3:
        suggestions.append(SuggestionItem(
            type="citation_improvement",
            priority="high",
            title="改善AI平台对品牌的负面评价",
            description=(
                f"当前负面评价占比{negative_rate:.0%}，"
                f"AI在引用品牌时倾向使用负面表述。"
                f"负面引用会严重影响用户对品牌的印象。"
            ),
            action=(
                "1. 分析负面引用的具体内容，找出主要批评点\n"
                "2. 针对性改进产品或服务，解决用户痛点\n"
                "3. 主动发布正面内容，稀释负面信息的影响\n"
                "4. 在官方渠道积极回应用户反馈和投诉"
            ),
            expected_impact="减少负面引用比例10-20个百分点",
            difficulty="hard",
        ))

    return suggestions


def generate_rule_based_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """
    基于规则生成优化建议（不依赖LLM）

    分析品牌数据差距，按照优先级生成可操作的建议。
    """
    all_suggestions: list[SuggestionItem] = []

    # 收集各类建议
    all_suggestions.extend(_generate_content_optimization_suggestions(ctx))
    all_suggestions.extend(_generate_platform_targeting_suggestions(ctx))
    all_suggestions.extend(_generate_competitor_gap_suggestions(ctx))
    all_suggestions.extend(_generate_query_expansion_suggestions(ctx))
    all_suggestions.extend(_generate_citation_improvement_suggestions(ctx))

    # 按优先级排序: high > medium > low
    priority_order = {"high": 0, "medium": 1, "low": 2}
    all_suggestions.sort(key=lambda s: priority_order.get(s.priority, 1))

    # 限制最多5条建议
    return all_suggestions[:5]


# ============================================================
# LLM 建议生成器
# ============================================================

OPTIMIZATION_PROMPT = """你是一个GEO（生成式引擎优化）专家。基于以下品牌数据，提供3-5条可操作的优化建议。

品牌: {brand_name}
当前评分: {overall_score}/100
评分维度:
- 提及率: {mention_rate_score}/{mention_rate_max} ({mention_rate_percentage}%)
- 推荐排名: {rank_score}/{rank_max} ({rank_percentage}%)
- 情感倾向: {sentiment_score}/{sentiment_max} ({sentiment_percentage}%)
- 引用质量: {citation_score}/{citation_max} ({citation_percentage}%)
- 竞品对比: {competitive_score}/{competitive_max} ({competitive_percentage}%)

竞品对比数据:
{competitor_data_str}

情感分析:
{sentiment_data_str}

平台评分:
{platform_data_str}

请返回JSON格式:
{{
  "suggestions": [
    {{
      "type": "content_optimization" | "platform_targeting" | "competitor_gap" | "query_expansion" | "citation_improvement",
      "priority": "high" | "medium" | "low",
      "title": "建议标题",
      "description": "详细描述",
      "action": "具体操作步骤",
      "expected_impact": "预期效果",
      "difficulty": "easy" | "medium" | "hard"
    }}
  ]
}}

要求:
1. 每条建议必须基于数据，指出具体的差距和改进方向
2. 优先关注最弱的维度
3. 建议必须可操作，包含具体步骤
4. 预期效果要量化
5. 返回3-5条建议，按优先级从高到低排列
"""


async def generate_llm_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """
    使用DeepSeek LLM生成个性化优化建议

    如果LLM不可用或调用失败，回退到规则生成。
    """
    if not settings.ENABLE_LLM or not settings.DEEPSEEK_API_KEY:
        logger.info("LLM未启用或API Key未配置，使用规则生成建议")
        return generate_rule_based_suggestions(ctx)

    try:
        # 构建prompt
        competitor_data_str = json.dumps(ctx.competitor_data, ensure_ascii=False, indent=2)
        sentiment_data_str = json.dumps(ctx.sentiment_data, ensure_ascii=False, indent=2)
        platform_data_str = json.dumps(ctx.platform_scores, ensure_ascii=False, indent=2)

        prompt = OPTIMIZATION_PROMPT.format(
            brand_name=ctx.brand_name,
            overall_score=ctx.overall_score,
            mention_rate_score=round(ctx.mention_rate_score, 2),
            mention_rate_max=ctx.mention_rate_max,
            mention_rate_percentage=round(ctx.mention_rate_percentage, 1),
            rank_score=round(ctx.rank_score, 2),
            rank_max=ctx.rank_max,
            rank_percentage=round(ctx.rank_percentage, 1),
            sentiment_score=round(ctx.sentiment_score, 2),
            sentiment_max=ctx.sentiment_max,
            sentiment_percentage=round(ctx.sentiment_percentage, 1),
            citation_score=round(ctx.citation_score, 2),
            citation_max=ctx.citation_max,
            citation_percentage=round(ctx.citation_percentage, 1),
            competitive_score=round(ctx.competitive_score, 2),
            competitive_max=ctx.competitive_max,
            competitive_percentage=round(ctx.competitive_percentage, 1),
            competitor_data_str=competitor_data_str,
            sentiment_data_str=sentiment_data_str,
            platform_data_str=platform_data_str,
        )

        # 调用DeepSeek API
        from openai import OpenAI

        client = OpenAI(
            api_key=settings.DEEPSEEK_API_KEY,
            base_url="https://api.deepseek.com",
        )

        response = await asyncio.to_thread(
            client.chat.completions.create,
            model="deepseek-chat",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3,
            max_tokens=2000,
        )

        content = response.choices[0].message.content
        if not content:
            raise ValueError("LLM返回空响应")

        # 提取JSON
        json_str = _extract_json(content)
        result = json.loads(json_str)

        # 解析建议
        suggestions: list[SuggestionItem] = []
        for item in result.get("suggestions", []):
            # 验证type字段
            valid_types = {
                "content_optimization", "platform_targeting",
                "competitor_gap", "query_expansion", "citation_improvement",
            }
            suggestion_type = item.get("type", "content_optimization")
            if suggestion_type not in valid_types:
                suggestion_type = "content_optimization"

            # 验证priority字段
            valid_priorities = {"high", "medium", "low"}
            priority = item.get("priority", "medium")
            if priority not in valid_priorities:
                priority = "medium"

            # 验证difficulty字段
            valid_difficulties = {"easy", "medium", "hard"}
            difficulty = item.get("difficulty", "medium")
            if difficulty not in valid_difficulties:
                difficulty = "medium"

            suggestions.append(SuggestionItem(
                type=suggestion_type,
                priority=priority,
                title=item.get("title", "优化建议"),
                description=item.get("description", ""),
                action=item.get("action", ""),
                expected_impact=item.get("expected_impact", ""),
                difficulty=difficulty,
            ))

        if not suggestions:
            logger.warning("LLM未返回有效建议，回退到规则生成")
            return generate_rule_based_suggestions(ctx)

        return suggestions[:5]

    except Exception as e:
        logger.error(f"LLM生成建议失败: {e}，回退到规则生成")
        return generate_rule_based_suggestions(ctx)


def _extract_json(text: str) -> str:
    """从文本中提取JSON"""
    import re

    # 尝试直接解析
    try:
        json.loads(text)
        return text
    except json.JSONDecodeError:
        pass

    # 尝试从代码块中提取
    json_pattern = r'```(?:json)?\s*([\s\S]*?)\s*```'
    match = re.search(json_pattern, text)
    if match:
        return match.group(1).strip()

    # 尝试找到第一个{到最后一个}之间的内容
    first_brace = text.find('{')
    last_brace = text.rfind('}')
    if first_brace != -1 and last_brace != -1 and last_brace > first_brace:
        return text[first_brace:last_brace + 1]

    raise ValueError(f"无法从响应中提取JSON: {text[:200]}")


# ============================================================
# 主入口：生成优化建议
# ============================================================

async def generate_suggestions(
    ctx: BrandAnalysisContext,
) -> list[SuggestionItem]:
    """
    生成优化建议

    如果ENABLE_LLM=True且有DeepSeek API Key，使用LLM生成个性化建议。
    否则使用基于规则的模板建议。
    """
    if settings.ENABLE_LLM and settings.DEEPSEEK_API_KEY:
        return await generate_llm_suggestions(ctx)
    return generate_rule_based_suggestions(ctx)


def build_context_from_scoring_result(
    brand_name: str,
    scoring_result: ScoringResultV2,
    competitor_data: dict[str, Any] | None = None,
    sentiment_data: dict[str, int] | None = None,
    platform_scores: dict[str, float] | None = None,
    total_queries: int = 0,
    mentioned_count: int = 0,
) -> BrandAnalysisContext:
    """
    从ScoringResultV2构建BrandAnalysisContext

    Args:
        brand_name: 品牌名称
        scoring_result: V2评分结果
        competitor_data: 竞品对比数据
        sentiment_data: 情感分析数据
        platform_scores: 平台评分数据
        total_queries: 总查询次数
        mentioned_count: 被提及次数

    Returns:
        BrandAnalysisContext: 品牌分析上下文
    """
    return BrandAnalysisContext(
        brand_name=brand_name,
        overall_score=scoring_result.overall_score,
        mention_rate_score=scoring_result.mention_rate.score,
        mention_rate_max=scoring_result.mention_rate.max_score,
        mention_rate_percentage=scoring_result.mention_rate.percentage,
        rank_score=scoring_result.recommendation_rank.score,
        rank_max=scoring_result.recommendation_rank.max_score,
        rank_percentage=scoring_result.recommendation_rank.percentage,
        sentiment_score=scoring_result.sentiment_score.score,
        sentiment_max=scoring_result.sentiment_score.max_score,
        sentiment_percentage=scoring_result.sentiment_score.percentage,
        citation_score=scoring_result.citation_quality.score,
        citation_max=scoring_result.citation_quality.max_score,
        citation_percentage=scoring_result.citation_quality.percentage,
        competitive_score=scoring_result.competitive_position.score,
        competitive_max=scoring_result.competitive_position.max_score,
        competitive_percentage=scoring_result.competitive_position.percentage,
        competitor_data=competitor_data or {},
        sentiment_data=sentiment_data or {},
        platform_scores=platform_scores or {},
        total_queries=total_queries,
        mentioned_count=mentioned_count,
    )
