"""
Account naming utilities for hierarchical account structure.
Implements Beancount-style account naming conventions.
"""

from typing import Optional

from .models import AccountType


# Mapping from internal account types to Beancount root names
ACCOUNT_TYPE_ROOTS = {
    AccountType.ASSET: "Assets",
    AccountType.LIABILITY: "Liabilities",
    AccountType.EQUITY: "Equity",
    AccountType.REVENUE: "Income",  # Beancount uses "Income" not "Revenue"
    AccountType.EXPENSE: "Expenses",
}


def format_hierarchical_account_name(
    account_type: AccountType,
    base_name: str,
    user_id: Optional[str] = None
) -> str:
    """
    Format account name in hierarchical Beancount-style.

    Examples:
        format_hierarchical_account_name(AccountType.ASSET, "Cash")
        → "Assets:Cash"

        format_hierarchical_account_name(AccountType.ASSET, "Accounts Receivable", "af983632")
        → "Assets:Receivable:User-af983632"

        format_hierarchical_account_name(AccountType.EXPENSE, "Food & Supplies")
        → "Expenses:Food:Supplies"

    Args:
        account_type: The type of account (asset, liability, etc.)
        base_name: The base name like "Cash", "Accounts Receivable", "Food & Supplies"
        user_id: Optional user ID for user-specific accounts

    Returns:
        Hierarchical account name string
    """
    root = ACCOUNT_TYPE_ROOTS[account_type]

    # Clean up the base name:
    # 1. Remove "Accounts" prefix (e.g., "Accounts Receivable" → "Receivable")
    # 2. Replace " & " with ":" for hierarchy (e.g., "Food & Supplies" → "Food:Supplies")
    # 3. Remove extra spaces
    clean_name = base_name.replace("Accounts ", "").replace(" & ", ":").strip()

    # Build hierarchical path
    if user_id:
        # For user-specific accounts, add user suffix
        # "Receivable" + "af983632" → "Receivable:User-af983632"
        user_suffix = f"User-{user_id[:8]}"
        return f"{root}:{clean_name}:{user_suffix}"
    else:
        # Regular account
        return f"{root}:{clean_name}"


def parse_legacy_account_name(name: str) -> tuple[str, Optional[str]]:
    """
    Parse legacy account names like "Accounts Receivable - af983632"
    into (base_name, user_id).

    Used only for migration from old format to hierarchical.

    Args:
        name: Legacy account name

    Returns:
        Tuple of (base_name, user_id or None)

    Examples:
        parse_legacy_account_name("Accounts Receivable - af983632")
        → ("Accounts Receivable", "af983632")

        parse_legacy_account_name("Cash")
        → ("Cash", None)
    """
    if " - " in name:
        parts = name.split(" - ", 1)
        base_name = parts[0].strip()
        user_id = parts[1].strip()
        return base_name, user_id
    else:
        return name, None


def format_account_display_name(hierarchical_name: str) -> str:
    """
    Convert hierarchical name to human-readable display name.

    Examples:
        format_account_display_name("Assets:Receivable:User-af983632")
        → "Accounts Receivable - af983632"

        format_account_display_name("Expenses:Food:Supplies")
        → "Food & Supplies"

    Args:
        hierarchical_name: Hierarchical account name

    Returns:
        Human-readable display name
    """
    parts = hierarchical_name.split(":")

    if len(parts) < 2:
        return hierarchical_name

    # Skip the root (Assets, Liabilities, etc.)
    body_parts = parts[1:]

    # Check for user suffix
    if len(body_parts) > 1 and body_parts[-1].startswith("User-"):
        user_suffix = body_parts[-1].replace("User-", "")
        base_parts = body_parts[:-1]

        # Reconstruct base name
        if base_parts[0] in ["Receivable", "Payable"]:
            base_name = f"Accounts {base_parts[0]}"
        else:
            base_name = " & ".join(base_parts)

        return f"{base_name} - {user_suffix}"
    else:
        # No user suffix, just join with &
        return " & ".join(body_parts)


def get_account_type_from_hierarchical(hierarchical_name: str) -> Optional[AccountType]:
    """
    Extract account type from hierarchical name.

    Examples:
        get_account_type_from_hierarchical("Assets:Cash")
        → AccountType.ASSET

        get_account_type_from_hierarchical("Income:Accommodation")
        → AccountType.REVENUE

    Args:
        hierarchical_name: Hierarchical account name

    Returns:
        AccountType or None if not found
    """
    parts = hierarchical_name.split(":")
    if not parts:
        return None

    root = parts[0]

    # Reverse lookup in ACCOUNT_TYPE_ROOTS
    for account_type, root_name in ACCOUNT_TYPE_ROOTS.items():
        if root == root_name:
            return account_type

    return None


def migrate_account_name(old_name: str, account_type: AccountType) -> str:
    """
    Migrate a legacy account name to hierarchical format.

    Args:
        old_name: Legacy account name like "Accounts Receivable - af983632"
        account_type: The account type

    Returns:
        Hierarchical account name

    Examples:
        migrate_account_name("Accounts Receivable - af983632", AccountType.ASSET)
        → "Assets:Receivable:User-af983632"

        migrate_account_name("Food & Supplies", AccountType.EXPENSE)
        → "Expenses:Food:Supplies"
    """
    base_name, user_id = parse_legacy_account_name(old_name)
    return format_hierarchical_account_name(account_type, base_name, user_id)


# Default chart of accounts with hierarchical names
DEFAULT_HIERARCHICAL_ACCOUNTS = [
    # Assets
    ("Assets:Cash", AccountType.ASSET, "Cash on hand"),
    ("Assets:Bank", AccountType.ASSET, "Bank account"),
    ("Assets:Lightning:Balance", AccountType.ASSET, "Lightning Network balance"),
    ("Assets:Receivable", AccountType.ASSET, "Money owed to the Castle"),

    # Liabilities
    ("Liabilities:Payable", AccountType.LIABILITY, "Money owed by the Castle"),

    # Equity
    ("Equity:MemberEquity", AccountType.EQUITY, "Member contributions"),
    ("Equity:RetainedEarnings", AccountType.EQUITY, "Accumulated profits"),

    # Revenue (Income in Beancount terminology)
    ("Income:Accommodation", AccountType.REVENUE, "Revenue from stays"),
    ("Income:Service", AccountType.REVENUE, "Revenue from services"),
    ("Income:Other", AccountType.REVENUE, "Other revenue"),

    # Expenses
    ("Expenses:Utilities", AccountType.EXPENSE, "Electricity, water, internet"),
    ("Expenses:Food:Supplies", AccountType.EXPENSE, "Food and supplies"),
    ("Expenses:Maintenance", AccountType.EXPENSE, "Repairs and maintenance"),
    ("Expenses:Other", AccountType.EXPENSE, "Miscellaneous expenses"),
]
