"""
Link action execution — 动作链接（link_type=ACTION）的执行逻辑。

访问 go/{alias}/{参数} 时，根据 action_config 执行预设动作。
当前支持的动作：
  - discord_send: 通过 Discord webhook 把消息发到指定频道并 @小黑

action_config 结构：
  {
    "action_type": "discord_send",
    "message_template": "@小黑 {query}",   # {query} 会被 URL 参数替换
  }

webhook URL 从环境变量 DISCORD_WEBHOOK_URL 读取（K8s secret links-discord-webhook）。

防重：传入 dedup_key 时，同一 key 在 DEDUP_TTL 秒内只发送一次（发送成功后写入缓存）。
"""
import hashlib
import logging
import os

import requests
from django.core.cache import cache

logger = logging.getLogger(__name__)

# 动作类型常量
ACTION_DISCORD_SEND = 'discord_send'

# Discord 单条消息上限 2000 字符，留出余量
MAX_MSG_LEN = 1900

# 防重窗口：同一内容 10 分钟内不重复发送
DEDUP_TTL = 600


def make_dedup_key(namespace: str, *parts: str) -> str:
    """生成防重 key：namespace + 各部分的 md5（避免超长/特殊字符问题）。"""
    raw = '|'.join(str(p) for p in parts if p)
    return f'dedup:{namespace}:{hashlib.md5(raw.encode("utf-8")).hexdigest()}'


def send_discord_message(message: str) -> None:
    """通过 Discord webhook 发送消息到配置的频道。"""
    webhook_url = os.environ.get('DISCORD_WEBHOOK_URL', '').strip()
    if not webhook_url:
        raise RuntimeError('服务端未配置 DISCORD_WEBHOOK_URL，无法发送')

    content = message[:MAX_MSG_LEN]
    try:
        resp = requests.post(webhook_url, json={'content': content}, timeout=15)
        resp.raise_for_status()
    except requests.exceptions.RequestException as e:
        logger.warning('[ACTION] discord webhook failed: %s', e)
        raise RuntimeError('发送到 Discord 失败，稍后再试')


def render_template(template: str, query: str) -> str:
    """把消息模板中的 {query} 替换为 URL 参数（其余占位符保持原样）。"""
    if not template:
        return query
    return template.replace('{query}', query)


def execute_action(action_config: dict, query: str, dedup_key: str = '') -> dict:
    """执行动作，返回 {success, message, discord_deeplink, deduped}。

    dedup_key 非空时启用防重：同一 key 在 DEDUP_TTL 秒内只发送一次；
    发送成功才占位，失败会释放（允许重试）。
    """
    config = action_config or {}
    action_type = config.get('action_type', '')
    deeplink = os.environ.get(
        'DISCORD_DEEPLINK',
        'https://discord.com/channels/1467846046590959798/1467846047089954952',
    )

    if action_type == ACTION_DISCORD_SEND:
        if not query.strip():
            return {
                'success': False,
                'message': '链接缺少参数：请在别名后面加上你的问题（go/别名/问题）',
                'discord_deeplink': '',
                'deduped': False,
            }
        # 防重：同 key 在窗口内已发送过 → 不重复发送，直接算成功（跳转 Discord）
        if dedup_key and not cache.add(dedup_key, '1', DEDUP_TTL):
            return {
                'success': True,
                'message': '已发送过，10 分钟内不重复发送',
                'discord_deeplink': deeplink,
                'deduped': True,
            }
        template = config.get('message_template', '@小黑 {query}')
        message = render_template(template, query)
        try:
            send_discord_message(message)
        except Exception:
            if dedup_key:
                cache.delete(dedup_key)  # 失败释放防重占位，允许重试
            raise
        return {
            'success': True,
            'message': '已投递到 Discord，回复会出现在 #general',
            'discord_deeplink': deeplink,
            'deduped': False,
        }

    return {
        'success': False,
        'message': f'未知的动作类型: {action_type}',
        'discord_deeplink': '',
        'deduped': False,
    }
