"""插件目录内按日错误日志（默认 UTC 日期文件名），保留可配置天数。"""

from __future__ import annotations

import re
from datetime import date, datetime, timedelta, timezone
from pathlib import Path

_LOG_STEM = re.compile(r"^(\d{4}-\d{2}-\d{2})$")


def plugin_logs_dir(plugin_root: Path) -> Path:
    return plugin_root / "logs"


def plugin_id_from_prefixed_tool(tool_name: str) -> str | None:
    """解析 ``plugin_<id>__<tool>`` 中的插件 id（仅限此类动态工具名）。"""
    m = re.match(r"^plugin_([a-z0-9_-]+)__(.+)$", tool_name)
    if not m:
        return None
    return m.group(1)


def _today_utc() -> date:
    return datetime.now(timezone.utc).date()


def prune_plugin_logs(logs_dir: Path, *, retention_days: int) -> None:
    """删除早于 ``retention_days`` 的 ``YYYY-MM-DD.log`` 文件。"""
    if retention_days < 1 or not logs_dir.is_dir():
        return
    cutoff = _today_utc() - timedelta(days=retention_days)
    for p in logs_dir.iterdir():
        if not p.is_file() or p.suffix != ".log":
            continue
        if not _LOG_STEM.match(p.stem):
            continue
        try:
            d = date.fromisoformat(p.stem)
        except ValueError:
            continue
        if d < cutoff:
            try:
                p.unlink()
            except OSError:
                pass


def write_plugin_log(
    plugin_root: Path,
    *,
    level: str,
    source: str,
    message: str,
    detail: str | None = None,
    retention_days: int = 7,
) -> Path | None:
    """
    追加一行 JSONL 风格可读日志到 ``<plugin>/logs/YYYY-MM-DD.log``（UTC 日期），并修剪旧文件。
    """
    try:
        plugin_root = plugin_root.resolve()
    except OSError:
        return None
    logs = plugin_logs_dir(plugin_root)
    logs.mkdir(parents=True, exist_ok=True)
    prune_plugin_logs(logs, retention_days=retention_days)
    day = _today_utc().isoformat()
    path = logs / f"{day}.log"
    ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
    line = f"{ts}\t{level}\t{source}\t{message}"
    if detail:
        line += f"\t{detail.replace(chr(9), ' ').replace(chr(10), ' ')[:8000]}"
    line += "\n"
    try:
        with path.open("a", encoding="utf-8", newline="\n") as f:
            f.write(line)
    except OSError:
        return None
    return path


def list_plugin_log_files(plugin_root: Path) -> list[str]:
    logs = plugin_logs_dir(plugin_root)
    if not logs.is_dir():
        return []
    out = sorted(
        p.name for p in logs.iterdir() if p.is_file() and p.suffix == ".log"
    )
    return out


def read_plugin_log_tail(
    plugin_root: Path,
    *,
    day: str | None = None,
    max_lines: int = 200,
) -> tuple[bool, str]:
    """读取指定日或当天日志尾部若干行；day 格式 ``YYYY-MM-DD``。"""
    logs = plugin_logs_dir(plugin_root)
    d = (day or _today_utc().isoformat()).strip()
    if not _LOG_STEM.match(d):
        return False, "invalid day format (use YYYY-MM-DD)"
    path = logs / f"{d}.log"
    if not path.is_file():
        return True, ""
    try:
        text = path.read_text(encoding="utf-8", errors="replace")
    except OSError as e:
        return False, str(e)
    lines = text.splitlines()
    tail = lines[-max(1, min(2000, max_lines)) :]
    return True, "\n".join(tail)
