"""XMind 16 file parser."""

import json
import os
import tempfile
from typing import Dict, List, Optional

from .exceptions import ParseError
from .sheet import Sheet
from .topic import Topic
from .utils import extract_zip_archive, remove_dir


def parse_xmind_file(filepath: str) -> Dict:
    """Parse an XMind file and return its content structure.
    
    Args:
        filepath: Path to the .xmind file.
        
    Returns:
        A dictionary containing the parsed content.
        
    Raises:
        ParseError: If the file cannot be parsed.
    """
    if not os.path.exists(filepath):
        raise ParseError(f"File not found: {filepath}")
    
    temp_dir = tempfile.mkdtemp()
    try:
        extract_zip_archive(filepath, temp_dir)
        return parse_xmind_directory(temp_dir)
    except Exception as e:
        raise ParseError(f"Failed to parse XMind file: {e}") from e
    finally:
        remove_dir(temp_dir)


def parse_xmind_directory(directory: str) -> Dict:
    """Parse an extracted XMind directory.
    
    Args:
        directory: Path to the extracted XMind directory.
        
    Returns:
        A dictionary containing the parsed content.
        
    Raises:
        ParseError: If the content cannot be parsed.
    """
    content_path = os.path.join(directory, "content.json")
    
    if not os.path.exists(content_path):
        raise ParseError(f"content.json not found in {directory}")
    
    try:
        with open(content_path, 'r', encoding='utf-8') as f:
            content = json.load(f)
    except json.JSONDecodeError as e:
        raise ParseError(f"Invalid JSON in content.json: {e}") from e
    
    return content


def parse_workbook(content: Dict) -> List[Sheet]:
    """Parse workbook content into Sheet objects.
    
    Args:
        content: The parsed content dictionary.
        
    Returns:
        A list of Sheet objects.
    """
    sheets = []
    
    # XMind 16 format
    if isinstance(content, list):
        for sheet_data in content:
            sheet = parse_sheet(sheet_data)
            if sheet:
                sheets.append(sheet)
    elif isinstance(content, dict):
        # Single sheet or wrapped content
        if "sheets" in content:
            for sheet_data in content["sheets"]:
                sheet = parse_sheet(sheet_data)
                if sheet:
                    sheets.append(sheet)
        else:
            sheet = parse_sheet(content)
            if sheet:
                sheets.append(sheet)
    
    return sheets


def parse_sheet(data: Dict) -> Optional[Sheet]:
    """Parse a sheet from dictionary data.
    
    Args:
        data: The sheet data dictionary.
        
    Returns:
        A Sheet object, or None if parsing fails.
    """
    if not isinstance(data, dict):
        return None
    
    try:
        return Sheet.from_dict(data)
    except Exception:
        return None


def parse_topic(data: Dict) -> Optional[Topic]:
    """Parse a topic from dictionary data.
    
    Args:
        data: The topic data dictionary.
        
    Returns:
        A Topic object, or None if parsing fails.
    """
    if not isinstance(data, dict):
        return None
    
    try:
        return Topic.from_dict(data)
    except Exception:
        return None
