"""
File utilities for Squad knowledge management.

Provides basic file I/O operations, YAML handling, and path management.
"""

import os
import yaml
from pathlib import Path
from typing import Dict, Any, Optional, Union, Tuple, List
from datetime import datetime
import uuid


def detect_ide_environment() -> Tuple[str, str]:
    """
    Detect which IDE environment Squad is running in.

    Returns:
        tuple[str, str]: (ide_name, ide_directory)
            - ide_name: "claude" or "cursor"
            - ide_directory: Full path to IDE config directory
    """
    home = Path.home()
    cursor_path = home / ".cursor" / "rules" / "00-squad-core.md"
    claude_path = home / ".claude" / "rules" / "00-squad-core.md"

    if cursor_path.exists():
        return "cursor", str(home / ".cursor")
    elif claude_path.exists():
        return "claude", str(home / ".claude")
    else:
        # Default to Claude Code
        return "claude", str(home / ".claude")


def get_knowledge_base_path() -> Path:
    """
    Get the path to the knowledge base directory.

    Returns:
        Path: ~/.thinkbank/knowledge/
    """
    return Path.home() / ".thinkbank" / "knowledge"


def ensure_dir(path: Union[str, Path]) -> None:
    """
    Ensure a directory exists, creating it if necessary.

    Args:
        path: Directory path to ensure exists
    """
    Path(path).mkdir(parents=True, exist_ok=True)


def generate_id(prefix: str = "kn") -> str:
    """
    Generate a unique ID for knowledge items.

    Args:
        prefix: Prefix for the ID (default: "kn" for knowledge)

    Returns:
        str: Unique ID in format: {prefix}-{timestamp}-{short-uuid}
    """
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
    short_uuid = str(uuid.uuid4())[:8]
    return f"{prefix}-{timestamp}-{short_uuid}"


def read_yaml(file_path: Union[str, Path]) -> Dict[str, Any]:
    """
    Read and parse a YAML file.

    Args:
        file_path: Path to YAML file

    Returns:
        Dict[str, Any]: Parsed YAML content

    Raises:
        FileNotFoundError: If file doesn't exist
        yaml.YAMLError: If YAML parsing fails
    """
    path = Path(file_path)

    if not path.exists():
        raise FileNotFoundError(f"File not found: {file_path}")

    with open(path, 'r', encoding='utf-8') as f:
        content = yaml.safe_load(f)

    return content if content is not None else {}


def write_yaml(file_path: Union[str, Path], data: Dict[str, Any]) -> None:
    """
    Write data to a YAML file.

    Args:
        file_path: Path to write to
        data: Dictionary to serialize as YAML

    Raises:
        yaml.YAMLError: If YAML serialization fails
    """
    path = Path(file_path)

    # Ensure parent directory exists
    ensure_dir(path.parent)

    with open(path, 'w', encoding='utf-8') as f:
        yaml.safe_dump(
            data,
            f,
            default_flow_style=False,
            allow_unicode=True,
            sort_keys=False
        )


def read_knowledge_file(file_path: Union[str, Path]) -> Tuple[Dict[str, Any], str]:
    """
    Read a knowledge file with YAML frontmatter and markdown content.

    Format:
        ---
        (YAML frontmatter)
        ---
        (Markdown content)

    Args:
        file_path: Path to knowledge file

    Returns:
        tuple[Dict[str, Any], str]: (frontmatter, content)

    Raises:
        FileNotFoundError: If file doesn't exist
        ValueError: If file format is invalid
    """
    path = Path(file_path)

    if not path.exists():
        raise FileNotFoundError(f"File not found: {file_path}")

    with open(path, 'r', encoding='utf-8') as f:
        raw_content = f.read()

    # Split frontmatter and content
    parts = raw_content.split('---', 2)

    if len(parts) < 3:
        raise ValueError(f"Invalid knowledge file format: {file_path}")

    frontmatter_str = parts[1].strip()
    content = parts[2].strip()

    # Parse frontmatter
    try:
        frontmatter = yaml.safe_load(frontmatter_str)
        if frontmatter is None:
            frontmatter = {}
    except yaml.YAMLError as e:
        raise ValueError(f"Invalid YAML frontmatter: {e}")

    return frontmatter, content


def write_knowledge_file(
    file_path: Union[str, Path],
    frontmatter: Dict[str, Any],
    content: str
) -> None:
    """
    Write a knowledge file with YAML frontmatter and markdown content.

    Args:
        file_path: Path to write to
        frontmatter: Dictionary for YAML frontmatter
        content: Markdown content
    """
    path = Path(file_path)

    # Ensure parent directory exists
    ensure_dir(path.parent)

    # Serialize frontmatter
    frontmatter_str = yaml.safe_dump(
        frontmatter,
        default_flow_style=False,
        allow_unicode=True,
        sort_keys=False
    )

    # Construct full content
    full_content = f"---\n{frontmatter_str}---\n\n{content}\n"

    with open(path, 'w', encoding='utf-8') as f:
        f.write(full_content)


def list_knowledge_files(
    knowledge_type: Optional[str] = None
) -> List[Path]:
    """
    List all knowledge files, optionally filtered by type.

    Args:
        knowledge_type: Optional type filter (skills, rules, patterns, etc.)

    Returns:
        list[Path]: List of knowledge file paths
    """
    base_path = get_knowledge_base_path()

    if knowledge_type:
        search_path = base_path / knowledge_type
        if not search_path.exists():
            return []
        return sorted(search_path.glob("*.md"))
    else:
        # Search all subdirectories
        files = []
        for subdir in ['skills', 'rules', 'patterns', 'domain', 'user', 'lessons']:
            subdir_path = base_path / subdir
            if subdir_path.exists():
                files.extend(subdir_path.glob("*.md"))
        return sorted(files)


def get_file_age_days(file_path: Union[str, Path]) -> float:
    """
    Get the age of a file in days.

    Args:
        file_path: Path to file

    Returns:
        float: Age in days
    """
    path = Path(file_path)

    if not path.exists():
        return 0.0

    mtime = path.stat().st_mtime
    now = datetime.now().timestamp()
    age_seconds = now - mtime

    return age_seconds / (24 * 3600)
