"""Vault adoption — point AgntSpace at a user-chosen folder.

Two modes only:
1. OFF (default) — AgntSpace runs against its configured root_dir.
2. DIRECT — The user picks a folder (often an existing Obsidian vault) and
   AgntSpace makes its `agntspace/` home inside it. No file-level sync — both
   tools read and write the same files. This is the canonical way to pair
   with Obsidian.

There is no folder-level sync mode and no obsidian-cli bridge. Direct mode
supersedes both.
"""

from __future__ import annotations

import logging
import shutil
from pathlib import Path

log = logging.getLogger(__name__)

_IDENTITY_FILES = ("SOUL.md", "USER.md", "PROFILE.md", "CONTRACT.md", "TRUST.md")  # arch:deterministic — structural identity-file list synced between vault and app_dir; layout invariant


class VaultSync:
    """Vault adoption helper.

    Owns the "point AgntSpace at this folder" operation and reports the
    current adoption status. Nothing here touches user content — only the
    agent's own `agntspace/` subtree.
    """

    def __init__(
        self,
        vault_dir: Path,
        external_dir: Path | None = None,
        mode: str = "off",
    ) -> None:
        self._vault = vault_dir
        self._external = external_dir or Path("")
        self._mode = mode

    @property
    def mode(self) -> str:
        return self._mode

    @property
    def is_configured(self) -> bool:
        if self._mode == "off":
            return False
        return self._external.is_dir()

    def configure(self, mode: str, external_path: str = "") -> None:
        """Update mode and (optionally) the external root path."""
        self._mode = mode
        if external_path:
            self._external = Path(external_path)
        log.info("Vault adoption: mode=%s, path=%s", mode, external_path)

    def adopt_obsidian_vault(self, obsidian_path: str) -> dict:
        """Point AgntSpace at a folder as its vault (direct mode).

        Creates `agntspace/` inside the folder and copies the current
        identity files over if the target doesn't already have them.
        User's existing files are never touched.
        """
        root_path = Path(obsidian_path)
        if not root_path.is_dir():
            return {"error": f"Path does not exist: {obsidian_path}"}

        is_obsidian = (root_path / ".obsidian").is_dir()
        target = root_path / "agntspace"

        from agntspace.setup.init import run_init

        run_init(vault_dir=root_path, minimal=True)

        copied: list[str] = []
        for name in _IDENTITY_FILES:
            src = self._vault / "system" / "identity" / name
            dst = target / "system" / "identity" / name
            if src.is_file() and not dst.exists():
                dst.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(src, dst)
                copied.append(f"system/identity/{name}")

        mem_src = self._vault / "memory" / "MEMORY.md"
        mem_dst = target / "memory" / "MEMORY.md"
        if mem_src.is_file() and not mem_dst.exists():
            mem_dst.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy2(mem_src, mem_dst)
            copied.append("memory/MEMORY.md")

        self._mode = "direct"
        self._external = root_path

        log.info(
            "Adopted vault at %s (is_obsidian=%s, copied %d files)",
            obsidian_path, is_obsidian, len(copied),
        )
        return {
            "status": "adopted",
            "path": obsidian_path,
            "is_obsidian_vault": is_obsidian,
            "directories_created": ["agntspace/"],
            "files_copied": copied,
            "mode": "direct",
            "message": (
                f"AgntSpace is now using {obsidian_path} as its vault. "
                "All data stored in agntspace/ — your files are untouched. "
                "Restart the server to activate."
            ),
        }

    def status(self) -> dict:
        return {
            "mode": self._mode,
            "external_path": str(self._external),
            "configured": self.is_configured,
        }
