"""
生成各种各样的 Message 的函数集合
"""


import datetime
import functools
import re
from typing import Any

from nonebot_plugin_alconna import UniMessage

from konabot.common.username import get_username
from konabot.plugins.kona_ph.core.image import get_image_manager
from konabot.plugins.kona_ph.core.storage import (DailyPuzzleInfo, Puzzle,
                                                  PuzzleManager,
                                                  PuzzleSubmission)


def get_puzzle_description(puzzle: Puzzle, with_answer: bool = False) -> UniMessage[Any]:
    """
    获取一个谜题的描述
    """

    img_manager = get_image_manager()

    result = UniMessage.text(f"[KonaPH#{puzzle.index_id}] {puzzle.title}")
    result = result.text(f"\n\n{puzzle.content}")

    if puzzle.img_name:
        result = result.text("\n\n").image(
            raw=img_manager.read_puzzle_image(puzzle.img_name)
        )

    result = result.text(f"\n\n出题者：{get_username(puzzle.author_id)}")

    if with_answer:
        result = result.text(f"\n\n题目答案：{puzzle.flag}")
    else:
        result = result.text("\n\nAt 我或者私聊我「提交答案 答案」来提交你的解答")

    return result


def get_submission_message(
    puzzle: Puzzle,
    submission: PuzzleSubmission,
    daily_puzzle_info: DailyPuzzleInfo | None = None,
) -> str:
    """
    获得提交答案的反馈信息
    """

    if submission.success:
        rank = -1
        if daily_puzzle_info is not None:
            rank = len(daily_puzzle_info.success_users)
        return f"🎉 恭喜你答对了！你是今天第 {rank} 个解出来的！"
    if submission.hint_id >= 0 and (
        hint := puzzle.hints.get(submission.hint_id)
    ) is not None:
        if hint.is_checkpoint:
            hint_msg = "✨ 恭喜！这是本题的中间答案，加油！"
        else:
            hint_msg = "🤔 答错啦！请检查你的答案。"
        return f"{hint_msg}\n\n提示：{hint.message}"
    return "❌ 答错啦！请检查你的答案。"


def get_daily_report(
    manager: PuzzleManager,
    date: datetime.date,
) -> str | None:
    """
    获得某日的提交的报告信息
    """

    index_id = manager.daily_puzzle_of_date.get(date)
    if index_id is None:
        return None
    info = manager.daily_puzzle[index_id]
    puzzle = manager.puzzle_data[info.raw_id]

    msg = f"[KonaPH#{puzzle.index_id}] 「{puzzle.title}」解答报告\n\n"
    if len(info.success_users) == 0:
        msg += "昨日，无人解出此题 😭😭\n\n"
    else:
        msg += f"昨日，共有 {len(info.success_users)} 人解出此题。\n\n"
        msg += "前五名的解答者：\n\n"
        us = [(u, d) for u, d in info.success_users.items()]
        us = sorted(us, key=lambda t: t[1])
        us = us[:5]
        for u, _ in us:
            m = manager.submissions[puzzle.raw_id][u][-1]
            msg += f"- {get_username(u)} 于 {m.time.strftime('%H:%M')}\n"
        msg += "\n"
    msg += f"出题人：{get_username(puzzle.author_id)}"
    return msg


def get_daily_report_v2(manager: PuzzleManager, gid: int | None = None):
    p = manager.get_today_puzzle()
    if p is None:
        return "今天无题"
    msg = "==== 今日答题情况 ====\n\n"

    subcount = len(functools.reduce(
        lambda x, y: x + y,
        manager.submissions.get(p.raw_id, {}).values(),
        [],
    ))
    info = manager.daily_puzzle[p.index_id]

    msg += (
        f"总体情况：答对 {len(info.success_users)} / "
        f"参与 {len(info.tried_users)} / "
        f"提交 {subcount}\n"
    )

    success_users = sorted(list(info.success_users.items()), key=lambda v: v[1])
    for u, d in success_users:
        uname = u
        if re.match(r"^\d+$", u):
            uname = get_username(int(u), gid)
        t = d.strftime("%H:%M")
        tries = len(manager.submissions[p.raw_id][u])
        msg += f"\n- {uname} [🎉 {t} 完成 | {tries} 提交]"
    for u in info.tried_users - set(info.success_users.keys()):
        uname = u
        if re.match(r"^\d+$", u):
            uname = get_username(int(u), gid)
        tries = len(manager.submissions[p.raw_id][u])
        checkpoints_touched = len(set((
            s.hint_id for s in manager.submissions[p.raw_id][u]
            if (
                s.hint_id >= 0
                and s.hint_id in p.hints
                and p.hints[s.hint_id].is_checkpoint
            )
        )))
        checkpoint_message = ""
        if checkpoints_touched > 0:
            checkpoint_message = f" | 🚩 {checkpoints_touched} 记录点"
        msg += f"\n- {uname} [💦 {tries} 提交{checkpoint_message}]"

    return msg


def get_puzzle_info_message(manager: PuzzleManager, puzzle: Puzzle) -> UniMessage[Any]:
    image_manager = get_image_manager()

    status = "✅ 已准备，待发布" if puzzle.ready and not manager.is_puzzle_published(puzzle.raw_id) else \
    (f"🟢 已发布: #{puzzle.index_id}" if manager.is_puzzle_published(puzzle.raw_id) else "⚙️ 未准备")

    status_suffix = ""
    if puzzle.raw_id == manager.puzzle_pinned:
        status_suffix += " | 📌 已被管理员置顶"

    msg = UniMessage.text(
        f"--- 谜题信息 ---\n"
        f"Raw ID: {puzzle.raw_id}\n"
        f"出题者: {get_username(puzzle.author_id)} | {puzzle.author_id}\n"
        f"创建时间: {puzzle.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
        f"状态: {status}{status_suffix}\n\n"
        f"标题: {puzzle.title}\n"
        f"Flag: {puzzle.flag}\n\n"
        f"{puzzle.content}"
    )

    if puzzle.img_name:
        msg = msg.image(raw=image_manager.read_puzzle_image(puzzle.img_name))

    msg = msg.text(f"\n---------\n使用 `konaph ready {puzzle.raw_id}` 完成编辑")

    return msg


def get_puzzle_hint_list(puzzle: Puzzle) -> str:
    msg = f"==== {puzzle.title} 提示与中间答案 ====\n"
    if len(puzzle.hints) == 0:
        msg += "\n你没有添加任何中间答案。"
        return msg
    for hint_id, hint in puzzle.hints.items():
        n = {False: "[提示]", True: "[中间答案]"}[hint.is_checkpoint]
        msg += f"\n{n}[{hint_id}] {hint.pattern}"
        msg += f"\n  {hint.message}"
    return msg
