"""
Configuration loader for TurboSEO.

Handles loading and saving project configurations.
"""

import tomllib
from pathlib import Path

from turboseo.config.models import ProjectConfig

# Config directory name
CONFIG_DIR = ".turboseo"
CONFIG_FILE = "config.toml"
CONTEXT_FILE = "context.md"


def get_global_dir() -> Path:
    """Get the global TurboSEO config directory (~/.turboseo/)."""
    return Path.home() / ".turboseo"


def get_config_dir(project_path: Path | None = None) -> Path:
    """Get the .turboseo directory for a project."""
    if project_path is None:
        project_path = Path.cwd()
    return project_path / CONFIG_DIR


def find_project_root(start_path: Path | None = None) -> Path | None:
    """
    Find the project root by looking for .turboseo directory.

    Walks up from start_path until finding .turboseo or hitting root.
    """
    if start_path is None:
        start_path = Path.cwd()

    current = start_path.resolve()

    while current != current.parent:
        config_dir = current / CONFIG_DIR
        if config_dir.is_dir():
            return current
        current = current.parent

    return None


def load_config(project_path: Path | None = None) -> ProjectConfig | None:
    """
    Load project configuration.

    Args:
        project_path: Path to project root. If None, searches from cwd.

    Returns:
        ProjectConfig if found, None otherwise.
    """
    if project_path is None:
        project_path = find_project_root()
        if project_path is None:
            return None

    config_file = project_path / CONFIG_DIR / CONFIG_FILE
    if not config_file.exists():
        return None

    with open(config_file, "rb") as f:
        data = tomllib.load(f)

    # Load context file if it exists
    context_file = project_path / CONFIG_DIR / CONTEXT_FILE
    if context_file.exists():
        data["context"] = context_file.read_text()

    return ProjectConfig(**data)


def save_config(config: ProjectConfig, project_path: Path | None = None) -> Path:
    """
    Save project configuration.

    Args:
        config: ProjectConfig to save.
        project_path: Path to project root. If None, uses cwd.

    Returns:
        Path to the saved config file.
    """
    if project_path is None:
        project_path = Path.cwd()

    config_dir = project_path / CONFIG_DIR
    config_dir.mkdir(parents=True, exist_ok=True)

    config_file = config_dir / CONFIG_FILE

    # Convert to TOML-compatible dict
    data = config.model_dump(exclude={"context"})

    # Write TOML manually (tomllib only reads, no toml write in stdlib)
    lines = _dict_to_toml(data)
    config_file.write_text("\n".join(lines))

    # Write context to separate file if provided
    if config.context:
        context_file = config_dir / CONTEXT_FILE
        context_file.write_text(config.context)

    return config_file


def _dict_to_toml(data: dict, prefix: str = "") -> list[str]:
    """Convert a dict to TOML lines."""
    lines = []

    # Process simple values first
    for key, value in data.items():
        if isinstance(value, dict):
            continue  # Process tables after
        lines.append(_format_toml_value(key, value))

    # Process nested tables
    for key, value in data.items():
        if isinstance(value, dict):
            section = f"{prefix}.{key}" if prefix else key
            lines.append("")
            lines.append(f"[{section}]")
            lines.extend(_dict_to_toml(value, section))

    return lines


def _format_toml_value(key: str, value) -> str:
    """Format a single TOML key-value pair."""
    if isinstance(value, str):
        # Escape quotes and use double quotes
        escaped = value.replace("\\", "\\\\").replace('"', '\\"')
        return f'{key} = "{escaped}"'
    elif isinstance(value, bool):
        return f"{key} = {str(value).lower()}"
    elif isinstance(value, (int, float)):
        return f"{key} = {value}"
    elif isinstance(value, list):
        if not value:
            return f"{key} = []"
        if all(isinstance(v, str) for v in value):
            items = ", ".join(f'"{v}"' for v in value)
            return f"{key} = [{items}]"
        return f"{key} = {value}"
    else:
        return f"{key} = {repr(value)}"


def create_gitignore_entry(project_path: Path | None = None) -> bool:
    """
    Add .turboseo/ to .gitignore if not already present.

    Returns True if added, False if already present or no .gitignore.
    """
    if project_path is None:
        project_path = Path.cwd()

    gitignore = project_path / ".gitignore"

    entry = ".turboseo/"

    if gitignore.exists():
        content = gitignore.read_text()
        if entry in content or ".turboseo" in content:
            return False
        # Add to existing .gitignore
        with open(gitignore, "a") as f:
            if not content.endswith("\n"):
                f.write("\n")
            f.write(f"\n# TurboSEO config (local)\n{entry}\n")
        return True
    else:
        # Create new .gitignore
        gitignore.write_text(f"# TurboSEO config (local)\n{entry}\n")
        return True
