from __future__ import annotations

import json
import zipfile
from datetime import datetime, timezone
from io import BytesIO
from pathlib import Path
from typing import Any

from niannian.skills.loader import SkillLoader


def resolve_skills_root(home: Path) -> Path:
    candidates = [
        home.parent / "skills",
        home / "skills",
        Path("/app/skills"),
        Path(__file__).resolve().parents[2] / "skills",
    ]
    for p in candidates:
        if p.is_dir():
            return p
    return candidates[-1]


def export_skills(
    home: Path,
    loader: SkillLoader | None = None,
    *,
    name: str | None = None,
    project: str | None = None,
    tags: str | None = None,
    enabled_only: bool = True,
) -> dict[str, Any]:
    root = resolve_skills_root(home)
    loader = loader or SkillLoader(root)
    tag_filter = [t.strip() for t in (tags or "").split(",") if t.strip()]
    skills = loader.list_skills()
    if enabled_only:
        skills = [s for s in skills if s.enabled]
    if name:
        skills = [s for s in skills if s.name == name or name in s.path]
    if tag_filter:
        skills = [s for s in skills if any(t in s.body for t in tag_filter)]
    rows = [{"name": s.name, "body": s.body, "triggers": s.triggers} for s in skills]
    if name and len(rows) == 1:
        return {"name": rows[0]["name"], "body": rows[0]["body"]}
    return {"skills": rows, "count": len(rows), "project": project}


def write_export_mirror(home: Path, loader: SkillLoader | None = None, *, mirror_dir: str = "skills/export") -> Path:
    """将启用 Skill 写入 skills/export/ 镜像目录。"""
    root = resolve_skills_root(home)
    loader = loader or SkillLoader(root)
    out = root / "export"
    out.mkdir(parents=True, exist_ok=True)
    manifest: list[dict[str, str]] = []
    for skill in loader.list_skills():
        if not skill.enabled:
            continue
        dest = out / skill.name / "SKILL.md"
        dest.parent.mkdir(parents=True, exist_ok=True)
        src = Path(skill.path)
        if src.is_file():
            dest.write_text(src.read_text(encoding="utf-8"), encoding="utf-8")
        manifest.append({"name": skill.name, "path": str(dest.relative_to(root))})
    manifest_path = out / "manifest.json"
    manifest_path.write_text(
        json.dumps({"updated_at": datetime.now(timezone.utc).isoformat(), "skills": manifest}, ensure_ascii=False, indent=2)
        + "\n",
        encoding="utf-8",
    )
    return out


def build_export_bundle(home: Path, loader: SkillLoader | None = None) -> tuple[bytes, dict[str, Any]]:
    """打包 export 目录为 zip bytes + manifest。"""
    out = write_export_mirror(home, loader)
    buf = BytesIO()
    manifest: dict[str, Any] = {"files": [], "created_at": datetime.now(timezone.utc).isoformat()}
    with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
        for path in out.rglob("*"):
            if path.is_file():
                arc = str(path.relative_to(out))
                zf.write(path, arcname=arc)
                manifest["files"].append(arc)
    return buf.getvalue(), manifest
