"""Utilities for managing .gitignore files."""

import logging
import os
from pathlib import Path

logger = logging.getLogger(__name__)


def find_gitignore(start_path: Path) -> Path | None:
    """
    Find the nearest .gitignore file by traversing up the directory tree.

    Args:
        start_path: The directory to start searching from

    Returns:
        Path to the .gitignore file if found, None otherwise
    """
    current = Path(start_path).resolve()

    while current != current.parent:
        gitignore_path = current / ".gitignore"
        if gitignore_path.exists():
            return gitignore_path

        # Check if this is a git repository
        if (current / ".git").exists():
            # Create .gitignore if it doesn't exist in a git repo
            gitignore_path.touch()
            return gitignore_path

        current = current.parent

    return None


def add_to_gitignore(directory: Path | str, pattern: str, verbose: bool = False) -> bool:
    """
    Add a pattern to the nearest .gitignore file.

    Args:
        directory: The directory to start searching from
        pattern: The pattern to add to .gitignore
        verbose: Whether to print verbose output

    Returns:
        True if pattern was added, False otherwise
    """
    directory = Path(directory).resolve()
    gitignore_path = find_gitignore(directory)

    if not gitignore_path:
        if verbose:
            logger.info("No .gitignore found in git repository hierarchy")
        return False

    # Read existing patterns
    existing_patterns = set()
    if gitignore_path.exists():
        with open(gitignore_path, "r") as f:
            existing_patterns = {line.strip() for line in f if line.strip() and not line.startswith("#")}

    # Check if pattern already exists
    if pattern in existing_patterns:
        if verbose:
            logger.info(f"Pattern '{pattern}' already exists in {gitignore_path}")
        return False

    # Add the pattern
    try:
        with open(gitignore_path, "a") as f:
            # Add newline if file doesn't end with one
            if gitignore_path.exists() and gitignore_path.stat().st_size > 0:
                with open(gitignore_path, "rb") as rf:
                    rf.seek(-1, os.SEEK_END)
                    if rf.read(1) != b"\n":
                        f.write("\n")

            # Add comment and pattern
            # Only add leading newline if file has content
            if gitignore_path.stat().st_size > 0:
                f.write("\n")
            f.write("# Protected dataset (added by easy-dataset-share)\n")
            f.write(f"{pattern}\n")
        if verbose:
            logger.info(f"Added '{pattern}' to {gitignore_path}")
        return True
    except PermissionError as e:
        logger.error(f"Permission denied when writing to {gitignore_path}: {e}")
        if verbose:
            logger.error("❌ Could not update .gitignore: Permission denied. Please check file permissions.")
        return False


def get_relative_pattern(base_dir: Path, target_dir: Path) -> str:
    """
    Get the relative path pattern for gitignore.

    Args:
        base_dir: The directory containing .gitignore
        target_dir: The directory to ignore

    Returns:
        The relative path pattern
    """
    try:
        # Get relative path
        rel_path = target_dir.relative_to(base_dir)
        # Ensure it ends with / to indicate directory
        pattern = str(rel_path) + "/"
        # Convert Windows paths to Unix style
        pattern = pattern.replace("\\", "/")
        return pattern
    except ValueError:
        # If target is not relative to base, use absolute pattern
        pattern = str(target_dir) + "/"
        return pattern.replace("\\", "/")


def auto_add_to_gitignore(directory: Path | str, verbose: bool = False) -> bool:
    """
    Automatically add a directory to .gitignore if in a git repository.

    Args:
        directory: The directory to add to .gitignore
        verbose: Whether to print verbose output

    Returns:
        True if added successfully, False otherwise
    """
    directory = Path(directory).resolve()
    gitignore_path = find_gitignore(directory)

    if not gitignore_path:
        return False

    # Get the directory containing .gitignore
    gitignore_dir = gitignore_path.parent

    # Get relative pattern
    pattern = get_relative_pattern(gitignore_dir, directory)

    # Add to gitignore
    return add_to_gitignore(directory, pattern, verbose)
