"""XMind 16 file builder."""

import json
import os
import tempfile
import time
from typing import List

from .exceptions import WriteError
from .sheet import Sheet
from .topic import Topic
from .utils import create_zip_archive, ensure_dir, remove_dir


def build_xmind_file(sheets: List[Sheet], filepath: str) -> None:
    """Build an XMind file from sheets.
    
    Args:
        sheets: List of Sheet objects to include.
        filepath: Output path for the .xmind file.
        
    Raises:
        WriteError: If the file cannot be written.
    """
    temp_dir = tempfile.mkdtemp()
    try:
        build_xmind_directory(sheets, temp_dir)
        create_zip_archive(temp_dir, filepath)
    except Exception as e:
        raise WriteError(f"Failed to write XMind file: {e}") from e
    finally:
        remove_dir(temp_dir)


def build_xmind_directory(sheets: List[Sheet], directory: str) -> None:
    """Build XMind content in a directory.
    
    Args:
        sheets: List of Sheet objects.
        directory: Output directory path.
        
    Raises:
        WriteError: If the content cannot be written.
    """
    ensure_dir(directory)
    
    # Build content.json
    content = build_content(sheets)
    content_path = os.path.join(directory, "content.json")
    
    try:
        with open(content_path, 'w', encoding='utf-8') as f:
            json.dump(content, f, ensure_ascii=False, indent=2)
    except Exception as e:
        raise WriteError(f"Failed to write content.json: {e}") from e
    
    # Build metadata.json (XMind 16 format)
    metadata = {
        "dataStructureVersion": "2",
        "layoutEngineVersion": "4",
        "creator": {
            "name": "py-xmind16",
            "version": "0.1.0"
        }
    }
    
    metadata_path = os.path.join(directory, "metadata.json")
    try:
        with open(metadata_path, 'w', encoding='utf-8') as f:
            json.dump(metadata, f, ensure_ascii=False, indent=2)
    except Exception as e:
        raise WriteError(f"Failed to write metadata.json: {e}") from e
    
    # Build manifest.json
    manifest = {
        "file-entries": {
            "content.json": {},
            "metadata.json": {},
            "content.xml": {}
        }
    }
    
    manifest_path = os.path.join(directory, "manifest.json")
    try:
        with open(manifest_path, 'w', encoding='utf-8') as f:
            json.dump(manifest, f, ensure_ascii=False, indent=2)
    except Exception as e:
        raise WriteError(f"Failed to write manifest.json: {e}") from e
    
    # Build content.xml (complete version for XMind 16 compatibility)
    content_xml = build_content_xml(sheets)
    content_xml_path = os.path.join(directory, "content.xml")
    try:
        with open(content_xml_path, 'w', encoding='utf-8') as f:
            f.write(content_xml)
    except Exception as e:
        raise WriteError(f"Failed to write content.xml: {e}") from e


def build_content(sheets: List[Sheet]) -> List[dict]:
    """Build content structure from sheets.
    
    Args:
        sheets: List of Sheet objects.
        
    Returns:
        A list of sheet dictionaries.
    """
    return [sheet.to_dict() for sheet in sheets]


def build_content_xml(sheets: List[Sheet]) -> str:
    """Build complete content.xml for XMind 16 compatibility.
    
    Args:
        sheets: List of Sheet objects.
        
    Returns:
        XML string.
    """
    timestamp = str(int(time.time() * 1000))
    
    lines = []
    lines.append('<?xml version="1.0" encoding="UTF-8" standalone="no"?>')
    lines.append('<xmap-content xmlns="urn:xmind:xmap:xmlns:content:2.0" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" modified-by="py-xmind16" timestamp="' + timestamp + '" version="2.0">')
    
    for sheet in sheets:
        lines.append('  <sheet id="' + sheet.id + '" modified-by="py-xmind16" timestamp="' + timestamp + '">')
        if sheet.root_topic:
            # Build topic XML using string concatenation
            topic_xml = _build_topic_xml_string(sheet.root_topic, 2)
            lines.append(topic_xml)
        lines.append('  </sheet>')
    
    lines.append('</xmap-content>')
    
    return '\n'.join(lines)


def _build_topic_xml_string(topic: Topic, indent_level: int) -> str:
    """Build XML for a topic and its children using string concatenation.
    
    This function builds the complete XML for a topic including opening tag,
    title, children, and closing tag. Using string concatenation avoids
    issues with list modification during recursion.
    
    Args:
        topic: The topic to convert.
        indent_level: Current indentation level.
        
    Returns:
        XML string for the topic.
    """
    indent = '  ' * indent_level
    timestamp = str(int(time.time() * 1000))
    
    parts = []
    # Topic opening tag
    parts.append(indent + '<topic id="' + topic.id + '" class="topic" modified-by="py-xmind16" timestamp="' + timestamp + '">')
    
    # Title
    parts.append(indent + '  <title>' + escape_xml(topic.title) + '</title>')
    
    # Children
    children = list(topic._subtopics)
    if children:
        parts.append(indent + '  <children>')
        parts.append(indent + '    <topics type="attached">')
        
        # Build each child's XML and add to parts
        for child in children:
            child_xml = _build_topic_xml_string(child, indent_level + 3)
            parts.append(child_xml)
        
        parts.append(indent + '    </topics>')
        parts.append(indent + '  </children>')
    
    # Topic closing tag
    parts.append(indent + '</topic>')
    
    return '\n'.join(parts)


def escape_xml(text: str) -> str:
    """Escape special XML characters.
    
    Args:
        text: The text to escape.
        
    Returns:
        Escaped text.
    """
    if text is None:
        return ""
    return (text
            .replace("&", "&amp;")
            .replace("<", "&lt;")
            .replace(">", "&gt;")
            .replace('"', "&quot;")
            .replace("'", "&apos;"))
