"""Path resolution utilities for ASA CLI v2."""

from pathlib import Path

from .errors import ConfigNotFoundError, SliceNotFoundError

CONFIG_FILENAME = "asa.config.json"


def find_project_root(start: Path | None = None) -> Path:
    """Find ASA project root by walking up to find asa.config.json.

    Args:
        start: Starting directory (default: cwd).

    Returns:
        Path to project root directory.

    Raises:
        ConfigNotFoundError: If asa.config.json not found in any parent.
    """
    current = (start or Path.cwd()).resolve()

    for directory in [current, *current.parents]:
        if (directory / CONFIG_FILENAME).exists():
            return directory

    raise ConfigNotFoundError(
        f"No {CONFIG_FILENAME} found. Run 'asa init' first to initialize an ASA project."
    )


def resolve_slice_path(domain: str, slice_name: str, project_root: Path) -> Path:
    """Resolve path to a slice directory.

    Args:
        domain: Domain name (e.g., 'auth').
        slice_name: Slice name (e.g., 'login').
        project_root: Project root directory.

    Returns:
        Path to domains/{domain}/{slice_name}/.
    """
    return project_root / "domains" / domain / slice_name


def resolve_shared_path(domain: str, project_root: Path) -> Path:
    """Resolve path to shared domain directory.

    Args:
        domain: Domain name (e.g., 'auth').
        project_root: Project root directory.

    Returns:
        Path to shared/{domain}/.
    """
    return project_root / "shared" / domain


def parse_domain_slice(domain_slice: str) -> tuple[str, str]:
    """Parse 'domain/slice' format into (domain, slice_name).

    Args:
        domain_slice: Slash-separated identifier (e.g., 'auth/login').

    Returns:
        Tuple of (domain, slice_name).

    Raises:
        ValueError: If format is invalid.
    """
    parts = domain_slice.split("/")
    if len(parts) != 2 or not all(parts):
        raise ValueError(
            f"Invalid slice identifier '{domain_slice}'. "
            f"Expected format: 'domain/slice' (e.g., 'auth/login')."
        )
    return parts[0], parts[1]


def kebab_to_pascal(name: str) -> str:
    """Convert kebab-case to PascalCase.

    Args:
        name: kebab-case string (e.g., 'reset-password').

    Returns:
        PascalCase string (e.g., 'ResetPassword').
    """
    return "".join(word.capitalize() for word in name.split("-"))


def snake_to_pascal(name: str) -> str:
    """Convert snake_case to PascalCase.

    Args:
        name: snake_case string (e.g., 'reset_password').

    Returns:
        PascalCase string (e.g., 'ResetPassword').
    """
    return "".join(word.capitalize() for word in name.split("_"))


def kebab_to_snake(name: str) -> str:
    """Convert kebab-case to snake_case.

    Args:
        name: kebab-case string (e.g., 'reset-password').

    Returns:
        snake_case string (e.g., 'reset_password').
    """
    return name.replace("-", "_")


def component_name(domain: str, slice_name: str, suffix: str = "Form") -> str:
    """Generate deterministic component name.

    Convention: {DomainPascal}{SlicePascal}{Suffix}
    No singularization — fully deterministic.

    Args:
        domain: Domain name in kebab-case.
        slice_name: Slice name in kebab-case.
        suffix: Component suffix ('Form', 'View', 'Widget').

    Returns:
        PascalCase component name (e.g., 'InvoicesCreateForm').
    """
    return f"{kebab_to_pascal(domain)}{kebab_to_pascal(slice_name)}{suffix}"


def hook_name(domain: str, slice_name: str) -> str:
    """Generate deterministic hook name.

    Convention: use{DomainPascal}{SlicePascal}

    Args:
        domain: Domain name in kebab-case.
        slice_name: Slice name in kebab-case.

    Returns:
        camelCase hook name (e.g., 'useInvoicesCreate').
    """
    return f"use{kebab_to_pascal(domain)}{kebab_to_pascal(slice_name)}"
