"""Workbook class for XMind 16."""

from typing import List, Optional, Union

from .builder import build_xmind_file
from .exceptions import ParseError, WriteError
from .parser import parse_workbook, parse_xmind_file
from .sheet import Sheet
from .utils import generate_id


class Workbook:
    """Represents an XMind workbook containing one or more sheets.
    
    A workbook is the top-level container for XMind content.
    """
    
    def __init__(self, id: Optional[str] = None):
        """Initialize a Workbook.
        
        Args:
            id: Optional unique identifier. If not provided, one will be generated.
        """
        self._id = id or generate_id()
        self._sheets: List[Sheet] = []
    
    @property
    def id(self) -> str:
        """Get the workbook's unique identifier."""
        return self._id
    
    @property
    def sheets(self) -> List[Sheet]:
        """Get a list of all sheets in the workbook."""
        return self._sheets.copy()
    
    @property
    def sheet_count(self) -> int:
        """Get the number of sheets in the workbook."""
        return len(self._sheets)
    
    def create_sheet(self, title: str = "Sheet") -> Sheet:
        """Create a new sheet and add it to the workbook.
        
        Args:
            title: The sheet title.
            
        Returns:
            The newly created sheet.
        """
        sheet = Sheet(title=title)
        self._sheets.append(sheet)
        return sheet
    
    def add_sheet(self, sheet: Sheet) -> None:
        """Add an existing sheet to the workbook.
        
        Args:
            sheet: The sheet to add.
        """
        self._sheets.append(sheet)
    
    def remove_sheet(self, sheet: Sheet) -> bool:
        """Remove a sheet from the workbook.
        
        Args:
            sheet: The sheet to remove.
            
        Returns:
            True if the sheet was found and removed, False otherwise.
        """
        if sheet in self._sheets:
            self._sheets.remove(sheet)
            return True
        return False
    
    def get_sheet(self, index: int) -> Optional[Sheet]:
        """Get a sheet by index.
        
        Args:
            index: The sheet index (0-based).
            
        Returns:
            The sheet at the given index, or None if out of range.
        """
        if 0 <= index < len(self._sheets):
            return self._sheets[index]
        return None
    
    def get_sheet_by_title(self, title: str) -> Optional[Sheet]:
        """Find a sheet by title.
        
        Args:
            title: The title to search for.
            
        Returns:
            The first matching sheet, or None if not found.
        """
        for sheet in self._sheets:
            if sheet.title == title:
                return sheet
        return None
    
    def save(self, filepath: str) -> None:
        """Save the workbook to an XMind file.
        
        Args:
            filepath: The output file path.
            
        Raises:
            WriteError: If the file cannot be written.
        """
        if not self._sheets:
            # Create a default sheet if none exists
            self.create_sheet()
        
        build_xmind_file(self._sheets, filepath)
    
    def to_bytes(self) -> bytes:
        """Convert the workbook to XMind file bytes.
        
        Returns:
            The workbook content as bytes.
            
        Raises:
            WriteError: If the content cannot be converted.
        """
        import tempfile
        import os
        
        with tempfile.NamedTemporaryFile(suffix='.xmind', delete=False) as f:
            temp_path = f.name
        
        try:
            self.save(temp_path)
            with open(temp_path, 'rb') as f:
                return f.read()
        finally:
            if os.path.exists(temp_path):
                os.remove(temp_path)
    
    @classmethod
    def load(cls, filepath: str) -> "Workbook":
        """Load a workbook from an XMind file.
        
        Args:
            filepath: The path to the .xmind file.
            
        Returns:
            A new Workbook instance.
            
        Raises:
            ParseError: If the file cannot be parsed.
        """
        content = parse_xmind_file(filepath)
        sheets = parse_workbook(content)
        
        workbook = cls()
        for sheet in sheets:
            workbook.add_sheet(sheet)
        
        return workbook
    
    @classmethod
    def from_bytes(cls, data: bytes) -> "Workbook":
        """Load a workbook from XMind file bytes.
        
        Args:
            data: The XMind file content as bytes.
            
        Returns:
            A new Workbook instance.
            
        Raises:
            ParseError: If the content cannot be parsed.
        """
        import tempfile
        import os
        
        with tempfile.NamedTemporaryFile(suffix='.xmind', delete=False) as f:
            f.write(data)
            temp_path = f.name
        
        try:
            return cls.load(temp_path)
        finally:
            if os.path.exists(temp_path):
                os.remove(temp_path)
    
    def __repr__(self) -> str:
        """Return a string representation of the workbook."""
        return f"Workbook(id={self._id[:8]}..., sheets={len(self._sheets)})"


def load_workbook(filepath: str) -> Workbook:
    """Load a workbook from an XMind file.
    
    This is a convenience function equivalent to Workbook.load().
    
    Args:
        filepath: The path to the .xmind file.
        
    Returns:
        A new Workbook instance.
    """
    return Workbook.load(filepath)
