"""Configuration loading and management.

Merges: defaults → global config → per-repo config.
"""

from __future__ import annotations

from dataclasses import dataclass, field, fields
from pathlib import Path

import yaml


GLOBAL_CONFIG_DIR = Path("~/.config/gwtm").expanduser()
GLOBAL_CONFIG_FILE = GLOBAL_CONFIG_DIR / "config.yaml"
WORKTREES_BASE = Path("~/.worktrees").expanduser()


@dataclass
class GwtConfig:
    """Resolved gwt configuration."""

    worktrees_base: Path = field(default_factory=lambda: WORKTREES_BASE)
    branch_prefix: str = "wt/"
    default_base_branch: str = "main"
    sync_strategy: str = "rebase"  # "rebase" or "merge"
    clone_base: Path | None = None
    auto_fetch: bool = True
    carry_patterns: list[str] = field(default_factory=list)
    carry_changes: bool = False

    def repo_worktrees_dir(self, repo_name: str) -> Path:
        """Return the worktree storage directory for a given repo."""
        return self.worktrees_base / repo_name


def load_config(repo_root: Path | None = None) -> GwtConfig:
    """Load config by merging defaults → global → per-repo."""
    config = GwtConfig()

    # Global config
    if GLOBAL_CONFIG_FILE.exists():
        _merge_yaml_into(config, GLOBAL_CONFIG_FILE)

    # Per-repo config
    if repo_root:
        repo_config = repo_root / ".gwtconfig.yaml"
        if repo_config.exists():
            _merge_yaml_into(config, repo_config)

    return config


def _merge_yaml_into(config: GwtConfig, path: Path) -> None:
    """Merge a YAML file's values into the config dataclass."""
    with open(path) as f:
        data = yaml.safe_load(f)

    if not isinstance(data, dict):
        return

    field_names = {f.name for f in fields(GwtConfig)}

    for key, value in data.items():
        if key not in field_names:
            continue
        if key in ("worktrees_base", "clone_base") and value is not None:
            value = Path(value).expanduser()
        setattr(config, key, value)


def ensure_global_config() -> None:
    """Create the default global config if it doesn't exist."""
    if GLOBAL_CONFIG_FILE.exists():
        return

    GLOBAL_CONFIG_DIR.mkdir(parents=True, exist_ok=True)

    defaults = {
        "worktrees_base": "~/.worktrees",
        "branch_prefix": "wt/",
        "default_base_branch": "main",
        "sync_strategy": "rebase",
        "auto_fetch": True,
        "carry_patterns": [],
        "carry_changes": False,
    }

    with open(GLOBAL_CONFIG_FILE, "w") as f:
        yaml.dump(defaults, f, default_flow_style=False, sort_keys=False)


def write_repo_config(dest: Path, default_base_branch: str) -> Path:
    """Write a per-repo .gwtconfig.yaml with commented-out defaults.

    The detected default branch is set; all other fields are commented out
    so the user can see what's available and uncomment as needed.
    """
    config_path = dest / ".gwtconfig.yaml"

    content = (
        "# gwtm per-repo configuration\n"
        "# Values here override the global config (~/.config/gwtm/config.yaml)\n"
        "\n"
        "# Default branch to create worktrees from\n"
        f"default_base_branch: {default_base_branch}\n"
        "\n"
        "# Prefix for worktree branches (e.g. \"wt/\" → \"wt/my-feature\")\n"
        "# branch_prefix: wt/\n"
        "\n"
        '# Sync strategy: "rebase" or "merge"\n'
        "# sync_strategy: rebase\n"
        "\n"
        "# Auto-fetch before operations\n"
        "# auto_fetch: true\n"
        "\n"
        "# File patterns to carry (symlink) into new worktrees\n"
        "# carry_patterns:\n"
        "#   - .env\n"
        "#   - .ai\n"
        "\n"
        "# Carry uncommitted changes to new worktrees\n"
        "# carry_changes: false\n"
    )

    config_path.write_text(content)
    return config_path


def get_all_managed_repos() -> list[str]:
    """Scan ~/.worktrees/ and return repo names that have worktree directories."""
    if not WORKTREES_BASE.exists():
        return []

    return sorted(
        d.name
        for d in WORKTREES_BASE.iterdir()
        if d.is_dir()
    )
