"""VP / system user addressing rules — spec §14."""

from __future__ import annotations

import re
from pathlib import Path
from typing import Any

from niannian.tenant.registry import TenantUserRegistry, normalize_username

_PROFILE_ADDRESS_RE = re.compile(r"^## 对用户的称呼\s*$", re.MULTILINE)

PINN_MASTER_ADDRESS = "主人"
USER_ADDRESS_LINE_PREFIX = "[对用户称呼]"


def extract_profile_calls_user_as(profile_md: str) -> str:
    """Read first non-empty line under ``## 对用户的称呼``."""
    match = _PROFILE_ADDRESS_RE.search(str(profile_md or ""))
    if not match:
        return ""
    tail = profile_md[match.end() :].lstrip("\n")
    for line in tail.splitlines():
        stripped = line.strip()
        if stripped.startswith("## "):
            break
        if stripped:
            return stripped
    return ""


def resolve_login_name(user_id: str, *, data_home: Path | str | None = None) -> str:
    """Tenant login display: display_name if set, else username."""
    uid = normalize_username(user_id)
    if data_home is not None:
        row = TenantUserRegistry(Path(data_home)).get_user(uid)
        if isinstance(row, dict):
            display = str(row.get("display_name") or "").strip()
            if display:
                return display
    return uid


def build_user_address_block(user_id: str, *, data_home: Path | str | None = None) -> str:
    """System user address — only pinn is 「主人」; others use login name."""
    if normalize_username(user_id) == "pinn":
        return PINN_MASTER_ADDRESS
    return resolve_login_name(user_id, data_home=data_home)


def guard_master_address(
    user_id: str,
    address: str,
    *,
    data_home: Path | str | None = None,
) -> str:
    """§14.1 — only user_id=pinn may be addressed as 「主人」."""
    value = str(address or "").strip()
    if value == PINN_MASTER_ADDRESS and normalize_username(user_id) != "pinn":
        return build_user_address_block(user_id, data_home=data_home)
    return value


def resolve_user_address(
    user_id: str,
    vp_meta: dict[str, Any] | None,
    profile_md: str,
    *,
    data_home: Path | str | None = None,
) -> str:
    """VP → user address: meta.calls_user_as > profile section > system default."""
    meta = vp_meta or {}
    raw = str(meta.get("calls_user_as") or "").strip()
    if raw:
        return guard_master_address(user_id, raw, data_home=data_home)

    from_profile = extract_profile_calls_user_as(profile_md)
    if from_profile:
        return guard_master_address(user_id, from_profile, data_home=data_home)

    return build_user_address_block(user_id, data_home=data_home)


def append_user_address_line(character_block: str, user_address: str) -> str:
    """Append ``[对用户称呼] {value}`` to character_block."""
    value = str(user_address or "").strip()
    if not value:
        return character_block
    line = f"{USER_ADDRESS_LINE_PREFIX} {value}"
    base = str(character_block or "").rstrip()
    if not base:
        return line
    return f"{base}\n{line}"


def sync_calls_user_as_from_profile(
    store: Any,
    vp_id: str,
    profile_md: str,
    *,
    fallback_profile_md: str | None = None,
) -> None:
    """After enrich — copy profile ``## 对用户的称呼`` into meta when meta field empty."""
    import yaml

    address = extract_profile_calls_user_as(profile_md)
    if not address and fallback_profile_md:
        address = extract_profile_calls_user_as(fallback_profile_md)
    if not address:
        return
    owner_id = normalize_username(getattr(store, "user_id", "") or "")
    if address == PINN_MASTER_ADDRESS and owner_id != "pinn":
        return

    meta_path = store.vp_dir(vp_id) / "meta.yaml"
    if not meta_path.is_file():
        return
    meta = yaml.safe_load(meta_path.read_text(encoding="utf-8")) or {}
    if not isinstance(meta, dict):
        return
    if str(meta.get("calls_user_as") or "").strip():
        return
    meta["calls_user_as"] = address
    meta_path.write_text(yaml.safe_dump(meta, allow_unicode=True, sort_keys=False), encoding="utf-8")


def resolve_user_address_for_vp(
    store: Any,
    vp_id: str,
    user_id: str,
    *,
    data_home: Path | str | None = None,
) -> str:
    """Load VP meta/profile and resolve address for equipped VP."""
    import yaml

    row = store.get(vp_id)
    meta_path = store.vp_dir(vp_id) / "meta.yaml"
    vp_meta: dict[str, Any] = {}
    if meta_path.is_file():
        loaded = yaml.safe_load(meta_path.read_text(encoding="utf-8")) or {}
        vp_meta = loaded if isinstance(loaded, dict) else {}
    return resolve_user_address(
        user_id,
        vp_meta,
        str(row.get("profile_md") or ""),
        data_home=data_home,
    )
