from __future__ import annotations

from collections.abc import Iterable

from trae_workspace_tool import templates
from trae_workspace_tool.models import Asset, Pack, Profile

DEFAULT_PROFILE = "internal-basic"
DEFAULT_PACK = "ops"


class RegistryError(ValueError):
    pass


def contains_text(expected: str, description: str):
    def validate(content: str) -> str | None:
        if expected in content:
            return None
        return description

    return validate


def profiles() -> dict[str, Profile]:
    enterprise_safety = Asset(
        ".trae/rules/enterprise-safety.md",
        templates.enterprise_safety_rule(),
        validators=(
            contains_text("alwaysApply: true", "missing alwaysApply: true"),
            contains_text("禁止读取", "missing secret handling policy"),
            contains_text("禁止将内部代码", "missing data exfiltration policy"),
        ),
    )
    return {
        "internal-basic": Profile(
            name="internal-basic",
            description="Enterprise intranet baseline safety policy for Trae workspaces.",
            assets=(enterprise_safety,),
        )
    }


def packs() -> dict[str, Pack]:
    ops_assets = (
        Asset(
            ".trae/rules/ops-safety.md",
            templates.ops_safety_rule(),
            validators=(contains_text("alwaysApply: true", "missing alwaysApply: true"),),
        ),
        Asset(
            ".trae/skills/ops-maintenance-automation/SKILL.md",
            templates.ops_skill(),
            validators=(contains_text("name: ops-maintenance-automation", "missing skill name"),),
        ),
        Asset("docs/trae-agents/ops-maintenance-agent-prompt.md", templates.agent_prompt()),
        Asset(
            "scripts/maintenance_check.py",
            templates.maintenance_script(),
            executable=True,
            validators=(
                contains_text("def ensure_inside_root", "missing root containment helper"),
                contains_text('"DRY-RUN"', "missing default dry-run marker"),
            ),
        ),
        Asset("docs/trae-ops-maintenance/README.md", templates.workspace_readme()),
    )
    return {
        "ops": Pack(
            name="ops",
            role="operations",
            description="Safe operations maintenance workspace with read-only and dry-run defaults.",
            assets=ops_assets,
        )
    }


def list_profiles() -> list[Profile]:
    return [profiles()[name] for name in sorted(profiles())]


def list_packs() -> list[Pack]:
    return [packs()[name] for name in sorted(packs())]


def get_profile(name: str) -> Profile:
    registry = profiles()
    try:
        return registry[name]
    except KeyError as exc:
        available = ", ".join(sorted(registry))
        raise RegistryError(f"unknown profile: {name} (available: {available})") from exc


def get_pack(name: str) -> Pack:
    registry = packs()
    try:
        return registry[name]
    except KeyError as exc:
        available = ", ".join(sorted(registry))
        raise RegistryError(f"unknown pack: {name} (available: {available})") from exc


def selected_assets(
    profile_name: str = DEFAULT_PROFILE,
    pack_name: str = DEFAULT_PACK,
) -> tuple[Asset, ...]:
    profile = get_profile(profile_name)
    pack = get_pack(pack_name)
    return ensure_unique_paths((*profile.assets, *pack.assets))


def ensure_unique_paths(assets: Iterable[Asset]) -> tuple[Asset, ...]:
    selected = tuple(assets)
    seen: set[str] = set()
    duplicates: list[str] = []
    for asset in selected:
        if asset.relative_path in seen:
            duplicates.append(asset.relative_path)
        seen.add(asset.relative_path)
    if duplicates:
        duplicate_list = ", ".join(sorted(set(duplicates)))
        raise RegistryError(f"duplicate asset path(s): {duplicate_list}")
    return selected
