import json
from flask import request, jsonify, Flask,Blueprint
import requests

import lark_oapi as lark
from lark_oapi.adapter.flask import *
from lark_oapi.api.im.v1 import *
from aidso_geo.core.down_load_bot import get_platforms, get_all_word_rank, get_sentiment_overview, \
    get_platforms_sentiment, get_url_top40, get_site_category, get_quote_mention_word_cloud, get_quto_statistics, \
    get_refer_rate_heatmap
from aidso_geo.core.feishu_snipaste import init_redis4, send_message, webhook_snipaste
from aidso_geo.utils import bh_utils, tos_utils

feishu_app = Blueprint("feishu_app", __name__)
from loguru import logger
VERIFICATION_TOKEN = "E7LUEWjOuj71AZ0H2rNMEec0o0sYYCJR"
BOT_OPEN_ID = "ou_102577da3586dabf877d4153ffe15d93"
r = init_redis4()

from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=2)

def run_webhook_snipaste_async(prompt_list):
    try:
        webhook_snipaste(prompt_list)
        logger.success(f"异步执行完成, 问题数量: {len(prompt_list)}")
    except Exception as e:
        logger.exception(f"异步执行 webhook_snipaste 失败: {e}")

import json
import requests
from flask import request, jsonify

# 这里换成你自己的飞书应用 App ID / App Secret
FEISHU_APP_ID = "cli_aaac8fa146fadbd5"
FEISHU_APP_SECRET = "N5omKg6d3sHi3JEIopQ8lcDAZKOiaNQ4"

# 你的飞书卡片 ID
FEISHU_CARD_TEMPLATE_ID = "AAqNYXIaKEOKR"



def get_tenant_access_token():
    """
    获取飞书 tenant_access_token
    """
    url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"

    payload = {
        "app_id": FEISHU_APP_ID,
        "app_secret": FEISHU_APP_SECRET
    }

    try:
        resp = requests.post(url, json=payload, timeout=10)


        data = resp.json()

        if data.get("code") != 0:
            raise Exception(f"获取 tenant_access_token 失败: {data}")
        return data.get("tenant_access_token")

    except Exception as e:
        logger.exception(f"获取 tenant_access_token 异常: {e}")
        raise


def send_feishu_template_card(chat_id):
    """
    发送飞书卡片搭建工具配置好的模板卡片
    卡片 ID: AAqNYXIaKEOKR
    """
    token = get_tenant_access_token()

    url = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id"

    # 模板卡片 content
    content = {
        "type": "template",
        "data": {
            "template_id": FEISHU_CARD_TEMPLATE_ID
        }
    }

    payload = {
        "receive_id": chat_id,
        "msg_type": "interactive",
        "content": json.dumps(content, ensure_ascii=False)
    }

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json; charset=utf-8"
    }


    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=10)
        data = resp.json()
        if data.get("code") != 0:
            logger.error(f"发送飞书模板卡片失败: {data}")
        return data
    except Exception as e:
        logger.exception(f"发送飞书模板卡片异常: {e}")
        raise


def parse_message_text(message):
    """
    解析飞书 text 消息内容
    message.content 是字符串，需要 json.loads 一次
    """
    content_str = message.get("content", "{}")

    try:
        content_json = json.loads(content_str)
    except Exception:
        content_json = {}

    text = content_json.get("text", "")

    return text


def send_message_v2(container_id,message):
    token = get_tenant_access_token()
    url = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id"

    payload = {
        "receive_id": container_id,
        "msg_type": "text",
        "content": json.dumps({
            "text": message
        }, ensure_ascii=False)
    }

    headers = {
       'Authorization': f'Bearer {token}',
       'Content-Type': 'application/json'
    }

    response = requests.request("POST", url, headers=headers, data=json.dumps(payload))



@feishu_app.route("/feishu/event/callback", methods=["POST"])
def feishu_event_callback():

    try:
        body = request.get_json(force=True)
    except Exception as e:
        logger.exception(f"解析 JSON 失败: {e}")
        body = {}

    if body.get("type") == "url_verification":
        return jsonify({"challenge": body["challenge"]})

    # 5. 获取事件类型
    event_type = (
        body.get("type")
        or body.get("header", {}).get("event_type")
        or body.get("event", {}).get("type")
        or "unknown"
    )

    # 6. 收到群里 @ 机器人消息
    if event_type == "im.message.receive_v1":
        try:
            event = body.get("event", {})
            message = event.get("message", {})

            chat_id = message.get("chat_id")
            chat_type = message.get("chat_type")
            message_id = message.get("message_id")
            message_type = message.get("message_type")

            text = parse_message_text(message)

            # 只处理文本消息
            if chat_id and message_type == "text":
                send_feishu_template_card(chat_id)
            else:
                logger.warning("不是 text 消息，或者 chat_id 为空，不发送卡片")

        except Exception as e:
            logger.exception(f"处理 im.message.receive_v1 失败: {e}")

        # 无论内部是否报错，都先返回成功，避免飞书重复推送
        return jsonify({
            "code": 0,
            "msg": "success"
        })

    # 7. 收到卡片点击 / 表单提交回调
    if event_type == "card.action.trigger":
        try:
            event = body.get("event", {})
            action = event.get("action", {})
            chat_id = event.get("message", {}).get("chat_id")
            # 表单值
            form_value = action.get("form_value", {})
            platdorm_list = form_value.get('platdorm_list')
            promp_list = form_value.get('promp_list')
            logger.success(json.dumps(form_value, ensure_ascii=False, indent=2))
            logger.success(f"platdorm_list{platdorm_list}")
            logger.success(f"promp_list{promp_list}")
            send_message_v2(chat_id,"----开始执行-----")
            # 这里后续可以写你自己的业务逻辑

        except Exception as e:
            logger.exception(f"处理 card.action.trigger 失败: {e}")

        return jsonify({
            "code": 0,
            "msg": "success"
        })

    # 8. 其他事件统一返回成功
    logger.success(f"未处理事件类型: {event_type}")

    return jsonify({
        "code": 0,
        "msg": "success"
    })

@feishu_app.route("/feishu/webhook", methods=["POST"])
def webhook():
    data = request.get_json(force=True)

    if data.get("type") == "url_verification":
        if data.get("token") != VERIFICATION_TOKEN:
            return jsonify({"msg": "forbidden"}), 403
        return jsonify({"challenge": data["challenge"]})

    if (data.get("header") or {}).get("event_type") == "im.message.receive_v1":
        msg = (data.get("event") or {}).get("message", {})

        if  msg.get("message_type") == "text":
            mentions = msg.get("mentions") or []
            is_at_bot = any(
                m.get("mentioned_type") == "bot" and
                (m.get("id") or {}).get("open_id") == BOT_OPEN_ID
                for m in mentions
            )
            if is_at_bot:
                text = json.loads(msg.get("content") or "{}").get("text", "")
                for m in mentions:
                    key = m.get("key")
                    if key:
                        text = text.replace(key, "").strip()
                if '|||' in text:
                    if r.scard('mt_third_task') > 0:
                        send_message(
                            "当前队列任务正在执行中，请稍后再试～")
                    else:
                        prompt_list = [i.strip() for i in text.split('|||') if i.strip()]
                        if prompt_list:
                            send_message("----开始执行-----")
                            executor.submit(run_webhook_snipaste_async, prompt_list)
                            logger.success(f"已提交线程池任务, 问题数量: {len(prompt_list)}")
                        else:
                            send_message("----格式错误 ||| 两边没有有效问题-----")
                else:
                    send_message("----格式错误需要用 ||| 分割每一个问题-----")
    return jsonify({"code": 0})

plat_form_map = {
    "DP": "deepseek网页版",
    "DB": "豆包网页版",
    "TXYB": "腾讯元宝",
    "TYQW": "通义千问",
    "KIMI": "kimi",
    "WXYY": "文心一言",
    "BDAI": "百度ai",
    "DYAI": "抖音ai",
    "DOUBA": "豆包手机版",
    "DPA": "deepseek手机版",
    "TYQWA":"通义千问千问手机版",
    "TXYBA":"腾讯元宝手机版"
}
def get_req_id(phone, begin, end):
    url = f"https://openapi.aidso.com/openapi/ywt/geoReqList?phone={phone}&begin={begin} 00:00:00&end={end} 23:59:59"

    payload = {}
    headers = {
        'Authorization': ''
    }

    response = requests.request("GET", url, headers=headers, data=payload)
    return response.json().get('data')

def success(data=None, msg="success"):
    return jsonify({
        "code": 200,
        "data": data,
        "msg": msg
    })


def fail(msg="fail", data=None):
    return jsonify({
        "code": 400,
        "data": data,
        "msg": msg
    })

@feishu_app.route("/feishu/export", methods=["POST"])
def qian_report():
    data = request.get_json() or {}

    phone = data.get("phone")
    begin = data.get("begin")
    end = data.get("end")
    brand_name = data.get("plan_name", [])
    platform = data.get("platform")  # 非必填，可能是 None

    if not phone:
        return fail("phone不能为空")

    if not begin:
        return fail("begin不能为空")

    if not end:
        return fail("end不能为空")

    # if not brand_name:
    #     return fail("brand_name不能为空")
    # if not isinstance(brand_name, list):
    #     return fail("brand_name必须是数组")

    if platform and not isinstance(platform, list):
        return fail("platform必须是数组")

    req_list = get_req_id(phone, begin, end)
    if not req_list:
        return fail("未查询到请求记录")
    try:
        req_time_map = {}
        req_brand_map = {}
        req_ids = []
        for b in brand_name:
            for item in req_list:
                if item.get('plan_name') == b:
                    req_id = item.get("req_id")
                    created_at = item.get("created_at")
                    req_ids.append(req_id)
                    req_time_map[req_id] = created_at
                    req_brand_map[req_id] = b

        req_id_sql = ",".join([f"'{req_id}'" for req_id in req_ids])
        if platform:
            platform_list = ",".join([f"'{p}'" for p in platform])
            query_sql = f"select * from geo_commit_task where reqId in ({req_id_sql}) and platform in ({platform_list})"
        else:
            query_sql = f"select * from geo_commit_task where reqId in ({req_id_sql})"
        query_list = bh_utils.query_data(query_sql)

        result = []
        if query_list:
            for q in query_list:
                r = {
                    "prompt": q.get('prompt'),
                    "platform": plat_form_map[q.get('platform')],
                    "content": tos_utils.get_string_from_tos(f"geo/{q.get('taskId')}/{q.get('platform')}/context.txt"),
                    "quote": tos_utils.get_string_from_tos(f"geo/{q.get('taskId')}/{q.get('platform')}/quote.txt"),
                    "created_at": req_time_map[q.get('reqId')],
                    "brand_name": req_brand_map[q.get('reqId')],
                }
                result.append(r)
        return success(result)
    except Exception as e:
        return fail('fail')


@feishu_app.route("/feishu/static", methods=["POST"])
def zhou_report():

    data = request.get_json() or {}

    phone = data.get("phone")
    begin = data.get("begin")
    end = data.get("end")
    brand_name = data.get("plan_name")
    question_list = data.get("question_list", [])

    if not phone:
        return fail("phone不能为空")

    if not begin:
        return fail("begin不能为空")

    if not end:
        return fail("end不能为空")
    if not brand_name:
        return fail("plan_name不能为空")

    # if not isinstance(question_list, list):
    #     return fail("question_list必须是数组")
    try:
        req_list = get_req_id(phone, begin, end)
        if not req_list:
            return fail("未查询到请求记录")

        req_time_map = {}
        req_ids = []
        brand_id = 0
        user_id = 0
        for item in req_list:
            item_plan_name = item.get('plan_name')
            if item_plan_name == brand_name:
                req_id = item.get("req_id")
                user_id = item.get("user_id")
                brand_id = item.get("brand_library_id")
                created_at = item.get("created_at")
                req_ids.append(req_id)
                req_time_map[req_id] = created_at

        if not brand_id or not user_id:
            return fail("未找到对应plan_name的数据")

        result = []
        platform_data = get_platforms(brand_id, user_id, begin, end, question_list) or {}
        if not isinstance(platform_data, dict):
            return fail("平台数据查询失败")

        geo_refer_rank_overview_vos = platform_data.get('geo_refer_rank_overview_vos') or []
        brand_overview = platform_data.get('brand_overview') or {}
        for item in geo_refer_rank_overview_vos:
            result.append({
                "平台": plat_form_map.get(item.get("platform"), item.get("platform")),
                "对话次数": item.get("ai_count"),
                "提及率": item.get("refer_rate"),
                "Top1提及率": item.get("top1_refer_rate"),
                "Top3提及率": item.get("top3_refer_rate"),
                "Top10提及率": item.get("top10_refer_rate"),
                "平均提及排名": item.get("avg_rank"),
                "提及好感度": item.get("sentiment_score"),
            })

        brand_overview_result = []
        brand_overview_result.append({
            '对话次数': brand_overview.get('ai_count'),
            '提及对话次数': brand_overview.get('valid_rank_count'),
            '提及率': brand_overview.get('refer_rate'),
            'top1提及率': brand_overview.get('top1_refer_rate'),
            'top3提及率': brand_overview.get('top3_refer_rate'),
            'top10提及率': brand_overview.get('top10_refer_rate'),
            '品牌提及次数': brand_overview.get('mention_count'),
            '平均提及排名': brand_overview.get('avg_rank'),
            '品牌提及好感度': brand_overview.get('sentiment_score'),
            '品牌得分': brand_overview.get('brand_score')
        })
        # 概览数据
        # 分平台数据

        all_word = get_all_word_rank(brand_id, user_id, begin, end, question_list) or []
        all_word_result = []
        for all in all_word:
            all_word_result.append({
                "品牌提及次数": all.get('ref_count'),
                "品牌名称": all.get("word"),
                "品牌得分": all.get("score"),
                "品牌提及率": all.get("rate"),
                "平均提及排名": all.get("avg_rank")
            })
        # 全部品牌词数据

        overview_result = []
        sentiment_overview = get_sentiment_overview(brand_id, user_id, begin, end, question_list) or {}

        overview_result.append(
            {
                "提及品牌AI对话次数": sentiment_overview.get('sentiment_count'),
                "品牌提及好感度": sentiment_overview.get('sentiment_score'),
                "正面情感": sentiment_overview.get('positive_count'),
                "中性情感": sentiment_overview.get('neutral_count'),
                "负面情感": sentiment_overview.get('negative_count'),
                "全部引用文章": sentiment_overview.get('article_count'),
                "有品牌内容引用文章": sentiment_overview.get('has_brand_count'),
                # todo 负面引用文章
                "负面引用文章": sentiment_overview.get('negative_count')
            }
        )
        platform_sentiment_result = []
        platform_sentiment = get_platforms_sentiment(brand_id, user_id, begin, end, question_list) or []
        for pla in platform_sentiment:
            sentiment_count = pla.get('sentiment_count') or 1
            platform_sentiment_result.append({
                "平台": plat_form_map.get(pla.get("platform"), pla.get("platform")),
                "正面": round((pla.get('positive_count') or 0) / sentiment_count, 2),
                "中性": round((pla.get('neutral_count') or 0) / sentiment_count, 2),
                "负面": round((pla.get('negative_count') or 0) / sentiment_count, 2),
                "提及品牌次数": pla.get('brand_words_count'),
                "引用来源": pla.get('source_count'),
            })

        platform_list = ["DB", "DP", "TYQW", "TXYB", "BDAI", "DOUBA", "DPA", "DYAI", "KIMI", "WXYY"]
        url_top_40 = get_url_top40(user_id, brand_id, begin, end, platform_list, question_list) or []
        url_top_40_result = []
        for url in url_top_40:
            url_top_40_result.append({
                "网站名称": url.get('site_name'),
                "引用次数": url.get('log_count'),
                "引用占比": url.get('quote_ratio_percent'),
            })

        site_category = get_site_category(brand_id, user_id, begin, end, platform_list, question_list) or []
        site_category_result = []
        for site in site_category:
            site_category_result.append({
                "站点类型": site.get('category'),
                "站点数量": site.get('site_count'),
                "引用文章数": site.get('resource_count'),
                "引用次数": site.get('total_log_count'),
                "引用率": site.get('quote_rate'),
            })

        quote_mention_word_cloud = get_quote_mention_word_cloud(brand_id, user_id, begin, end, question_list) or {}
        positive_top = quote_mention_word_cloud.get('positive_top') or []
        negative_top = quote_mention_word_cloud.get('negative_top') or []
        positive_top_result = []
        for positive in positive_top:
            positive_top_result.append({
                "关键词": positive.get('word'),
                "出现次数": positive.get('count'),
            })

        negative_top_result = []
        for negative in negative_top:
            negative_top_result.append({
                "关键词": negative.get('word'),
                "出现次数": negative.get('count'),
            })
        quto_statistics_result = []
        quto_statistics = get_quto_statistics(brand_id, user_id, begin, end, question_list) or {}
        quto_statistics_result.append({
            "引用文章数": quto_statistics.get('resource_count'),
            "引用次数": quto_statistics.get('total_log_count'),
            "引用网站": quto_statistics.get('site_count'),
        })

        refer_rate_heatmap = get_refer_rate_heatmap(brand_id, user_id, begin, end, question_list)
        static_data = {
            "brand_overview_result":brand_overview_result,
            "result":result,
            "all_word_result":all_word_result,
            "overview_result":overview_result,
            "platform_sentiment_result":platform_sentiment_result,
            "url_top_40_result":url_top_40_result,
            "site_category_result":site_category_result,
            "positive_top_result":positive_top_result,
            "negative_top_result":negative_top_result,
            "quto_statistics_result":quto_statistics_result,
            "refer_rate_heatmap":refer_rate_heatmap
        }
        return success(static_data)
    except Exception as e:
        logger.exception(f"/feishu/static处理失败: {e}")
        return  fail('fail')
