"""TikTok-specific CRDT document parser.

This module provides parsing for CRDT documents containing TikTok
post data with tiktokpost nodes.
"""

from __future__ import annotations

from datetime import UTC, datetime
from typing import TYPE_CHECKING, Any

from marqetive.utils.crdt.exceptions import CRDTEmptyDocumentError, CRDTParseError
from marqetive.utils.crdt.models import (
    ParsedTikTokDocument,
    TikTokPostContent,
)
from marqetive.utils.crdt.platforms.base import BaseCRDTParser

if TYPE_CHECKING:
    from pycrdt import Doc, XmlElement


class TikTokCRDTParser(BaseCRDTParser[ParsedTikTokDocument]):
    """Parser for TikTok CRDT documents.

    Handles parsing of tiktokpost nodes. Supports single video posts
    with location and music metadata.

    Validation rules:
        - Max 2200 characters for title
        - Video is required (at least 1 media item)
    """

    @property
    def platform_name(self) -> str:
        """Return the platform name."""
        return "tiktok"

    @property
    def root_node_type(self) -> str:
        """Return the root node type for TikTok."""
        return "tiktokpost"

    def parse_document(
        self,
        doc: Doc[Any],
        fragment_name: str = "default",
        *,
        include_auto_number: bool = False,  # noqa: ARG002
    ) -> ParsedTikTokDocument:
        """Parse a TikTok CRDT document.

        Args:
            doc: The pycrdt Doc object to parse
            fragment_name: Name of the XML fragment to parse

        Returns:
            ParsedTikTokDocument with parsed post

        Raises:
            CRDTEmptyDocumentError: If no post found
            CRDTParseError: If parsing fails
        """
        fragment = self._get_fragment(doc, fragment_name)
        raw_attributes = self._get_node_attributes(fragment)

        # Find the tiktokpost node
        post_nodes = self._find_nodes_by_type(fragment, self.root_node_type)

        if not post_nodes:
            raise CRDTEmptyDocumentError(
                "No TikTok post found in document",
                fragment_name=fragment_name,
            )

        # Parse the post
        try:
            post = self._parse_post(post_nodes[0])
        except Exception as e:
            raise CRDTParseError(
                f"Failed to parse TikTok post: {e}",
                platform=self.platform_name,
                node_type=self.root_node_type,
            ) from e

        return ParsedTikTokDocument(
            post=post,
            raw_attributes=raw_attributes,
            parsed_at=datetime.now(UTC),
        )

    def _parse_post(self, node: XmlElement) -> TikTokPostContent:
        """Parse a tiktokpost node.

        Args:
            node: The tiktokpost XML node

        Returns:
            TikTokPostContent with parsed data
        """
        attrs = self._get_node_attributes(node)

        # Read post ID from attrs
        post_id = attrs.get("id")
        if post_id is not None:
            post_id = str(post_id)

        # Extract title text
        title = self._extract_text(node)

        # Parse media via space-separated URL strings
        media = self._parse_media_urls(node, "media")

        # Read location as simple string
        location = attrs.get("location")
        if location is not None:
            location = str(location)

        # Read music as simple string
        music = attrs.get("music")
        if music is not None:
            music = str(music)

        return TikTokPostContent(
            id=post_id,
            title=title,
            media=media,
            location=location,
            music=music,
        )
