"""NFO XML generator for Kodi/XBMC format.

This module provides functions to generate tvshow.nfo XML files from
TVShowNFO Pydantic models, adapted from the scraper project.

Example:
    >>> from src.core.entities.nfo_models import TVShowNFO
    >>> nfo = TVShowNFO(title="Test Show", year=2020, tmdbid=12345)
    >>> xml_string = generate_tvshow_nfo(nfo)
"""

import logging
from typing import Optional

from lxml import etree

from src.config.settings import settings
from src.core.entities.nfo_models import TVShowNFO

logger = logging.getLogger(__name__)


def generate_tvshow_nfo(tvshow: TVShowNFO, pretty_print: bool = True) -> str:
    """Generate tvshow.nfo XML content from TVShowNFO model.
    
    Args:
        tvshow: TVShowNFO Pydantic model with metadata
        pretty_print: Whether to format XML with indentation
        
    Returns:
        XML string in Kodi/XBMC tvshow.nfo format
        
    Example:
        >>> nfo = TVShowNFO(title="Attack on Titan", year=2013)
        >>> xml = generate_tvshow_nfo(nfo)
    """
    root = etree.Element("tvshow")
    
    # Basic information
    _add_element(root, "title", tvshow.title)
    _add_element(root, "originaltitle", tvshow.originaltitle)
    _add_element(root, "showtitle", tvshow.showtitle)
    _add_element(root, "sorttitle", tvshow.sorttitle)
    _add_element(root, "year", str(tvshow.year) if tvshow.year else None)
    
    # Plot and description – always write <plot> even when empty so that
    # all NFO files have a consistent set of tags regardless of whether they
    # were produced by create or update.
    _add_element(root, "plot", tvshow.plot, always_write=True)
    _add_element(root, "outline", tvshow.outline)
    _add_element(root, "tagline", tvshow.tagline)
    
    # Technical details
    _add_element(root, "runtime", str(tvshow.runtime) if tvshow.runtime else None)
    
    # Content rating - prefer FSK if available and configured
    if getattr(settings, 'nfo_prefer_fsk_rating', True) and tvshow.fsk:
        _add_element(root, "mpaa", tvshow.fsk)
    else:
        _add_element(root, "mpaa", tvshow.mpaa)
    
    _add_element(root, "certification", tvshow.certification)
    
    # Status and dates
    _add_element(root, "premiered", tvshow.premiered)
    _add_element(root, "status", tvshow.status)
    _add_element(root, "dateadded", tvshow.dateadded)
    
    # Ratings
    if tvshow.ratings:
        ratings_elem = etree.SubElement(root, "ratings")
        for rating in tvshow.ratings:
            rating_elem = etree.SubElement(ratings_elem, "rating")
            if rating.name:
                rating_elem.set("name", rating.name)
            if rating.max_rating:
                rating_elem.set("max", str(rating.max_rating))
            if rating.default:
                rating_elem.set("default", "true")
            
            _add_element(rating_elem, "value", str(rating.value))
            if rating.votes is not None:
                _add_element(rating_elem, "votes", str(rating.votes))
    
    _add_element(root, "userrating", str(tvshow.userrating) if tvshow.userrating is not None else None)
    
    # IDs
    _add_element(root, "tmdbid", str(tvshow.tmdbid) if tvshow.tmdbid else None)
    _add_element(root, "imdbid", tvshow.imdbid)
    _add_element(root, "tvdbid", str(tvshow.tvdbid) if tvshow.tvdbid else None)
    
    # Legacy ID fields for compatibility
    _add_element(root, "id", str(tvshow.tvdbid) if tvshow.tvdbid else None)
    _add_element(root, "imdb_id", tvshow.imdbid)
    
    # Unique IDs
    for uid in tvshow.uniqueid:
        uid_elem = etree.SubElement(root, "uniqueid")
        uid_elem.set("type", uid.type)
        if uid.default:
            uid_elem.set("default", "true")
        uid_elem.text = uid.value
    
    # Multi-value fields
    for genre in tvshow.genre:
        _add_element(root, "genre", genre)
    
    for studio in tvshow.studio:
        _add_element(root, "studio", studio)
    
    for country in tvshow.country:
        _add_element(root, "country", country)
    
    for tag in tvshow.tag:
        _add_element(root, "tag", tag)
    
    # Thumbnails (posters, logos)
    for thumb in tvshow.thumb:
        thumb_elem = etree.SubElement(root, "thumb")
        if thumb.aspect:
            thumb_elem.set("aspect", thumb.aspect)
        if thumb.season is not None:
            thumb_elem.set("season", str(thumb.season))
        if thumb.type:
            thumb_elem.set("type", thumb.type)
        thumb_elem.text = str(thumb.url)
    
    # Fanart
    if tvshow.fanart:
        fanart_elem = etree.SubElement(root, "fanart")
        for fanart in tvshow.fanart:
            fanart_thumb = etree.SubElement(fanart_elem, "thumb")
            fanart_thumb.text = str(fanart.url)
    
    # Named seasons
    for named_season in tvshow.namedseason:
        season_elem = etree.SubElement(root, "namedseason")
        season_elem.set("number", str(named_season.number))
        season_elem.text = named_season.name
    
    # Actors
    for actor in tvshow.actors:
        actor_elem = etree.SubElement(root, "actor")
        _add_element(actor_elem, "name", actor.name)
        _add_element(actor_elem, "role", actor.role)
        _add_element(actor_elem, "thumb", str(actor.thumb) if actor.thumb else None)
        _add_element(actor_elem, "profile", str(actor.profile) if actor.profile else None)
        _add_element(actor_elem, "tmdbid", str(actor.tmdbid) if actor.tmdbid else None)
    
    # Additional fields
    _add_element(root, "trailer", str(tvshow.trailer) if tvshow.trailer else None)
    _add_element(root, "watched", "true" if tvshow.watched else "false")
    if tvshow.playcount is not None:
        _add_element(root, "playcount", str(tvshow.playcount))
    
    # Generate XML string
    xml_str = etree.tostring(
        root,
        pretty_print=pretty_print,
        encoding="unicode",
        xml_declaration=False
    )
    
    # Add XML declaration
    xml_declaration = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
    return xml_declaration + xml_str


def _add_element(
    parent: etree.Element,
    tag: str,
    text: Optional[str],
    always_write: bool = False,
) -> Optional[etree.Element]:
    """Add a child element to parent if text is not None or empty.
    
    Args:
        parent: Parent XML element
        tag: Tag name for child element
        text: Text content (None or empty strings are skipped
              unless *always_write* is True)
        always_write: When True the element is created even when
                      *text* is None/empty (the element will have
                      no text content).  Useful for tags like
                      ``<plot>`` that should always be present.
        
    Returns:
        Created element or None if skipped
    """
    if text is not None and text != "":
        elem = etree.SubElement(parent, tag)
        elem.text = text
        return elem
    if always_write:
        return etree.SubElement(parent, tag)
    return None


def validate_nfo_xml(xml_string: str) -> bool:
    """Validate NFO XML structure.
    
    Args:
        xml_string: XML content to validate
        
    Returns:
        True if valid XML, False otherwise
    """
    try:
        etree.fromstring(xml_string.encode('utf-8'))
        return True
    except etree.XMLSyntaxError as e:
        logger.error("Invalid NFO XML: %s", e)
        return False
