"""ODT export service using pypandoc.

This module provides the ODTExporter class for converting markdown content
to OpenDocument Text (ODT) format using pypandoc (Pandoc wrapper).

Pandoc is the industry standard for document conversion and handles all
markdown features natively. Note: Requires Pandoc to be installed on the
system or use pypandoc_binary which bundles it.
"""

import subprocess
from typing import Optional

from loguru import logger

# pypandoc is optional - used only to locate the bundled pandoc binary
try:
    import pypandoc

    PYPANDOC_AVAILABLE = True
except ImportError:
    pypandoc = None
    PYPANDOC_AVAILABLE = False

from .base import BaseExporter, ExportOptions, ExportResult
from .registry import ExporterRegistry

# Maximum content size (50 MB) to prevent OOM errors
MAX_CONTENT_SIZE = 50 * 1024 * 1024


@ExporterRegistry.register
class ODTExporter(BaseExporter):
    """Service for converting markdown to ODT using pypandoc.

    This exporter uses Pandoc (via pypandoc) to convert markdown content
    to OpenDocument Text format, which can be opened in LibreOffice Writer,
    Microsoft Word, and other office applications.

    Pandoc is the industry standard for document conversion and handles
    all markdown features (tables, code blocks, lists, etc.) natively.

    The conversion is performed entirely in memory by piping markdown
    to pandoc's stdin and capturing ODT output from stdout.
    """

    @property
    def format_name(self) -> str:
        return "odt"

    @property
    def file_extension(self) -> str:
        return ".odt"

    @property
    def mimetype(self) -> str:
        return "application/vnd.oasis.opendocument.text"

    def export(
        self,
        markdown_content: str,
        options: Optional[ExportOptions] = None,
    ) -> ExportResult:
        """Convert markdown content to ODT using Pandoc.

        The conversion runs entirely in memory: markdown is piped to
        pandoc's stdin and ODT bytes are captured from stdout, avoiding
        any temporary files on disk.

        Args:
            markdown_content: The markdown text to convert
            options: Optional export options (title, metadata)

        Returns:
            ExportResult with ODT content as bytes, filename, and mimetype

        Raises:
            ValueError: If content exceeds maximum size limit
            RuntimeError: If Pandoc conversion fails
        """
        try:
            # Check if pypandoc is available
            if not PYPANDOC_AVAILABLE:
                raise RuntimeError(
                    "ODT export requires pypandoc. Install with: pip install pypandoc-binary"
                )

            # Check content size limit to prevent OOM errors
            if len(markdown_content) > MAX_CONTENT_SIZE:
                raise ValueError(
                    f"Content exceeds maximum size of "
                    f"{MAX_CONTENT_SIZE // (1024 * 1024)} MB"
                )

            options = options or ExportOptions()

            # Prepend title if needed (for document formats like ODT)
            markdown_content = self._prepend_title_if_needed(
                markdown_content, options.title
            )

            # Add LDR attribution footer
            content_with_footer = self._add_footer(markdown_content)

            # Build pandoc args for metadata (sanitized)
            extra_args = []
            if options.title:
                safe_title = self._sanitize_metadata(options.title)
                extra_args.append(f"--metadata=title:{safe_title}")
            if options.metadata:
                if options.metadata.get("author"):
                    safe_author = self._sanitize_metadata(
                        options.metadata["author"]
                    )
                    extra_args.append(f"--metadata=author:{safe_author}")
                if options.metadata.get("date"):
                    safe_date = self._sanitize_metadata(
                        options.metadata["date"]
                    )
                    extra_args.append(f"--metadata=date:{safe_date}")

            # Convert in memory: pipe markdown via stdin, capture ODT from stdout
            pandoc_path = pypandoc.get_pandoc_path()
            cmd = [pandoc_path, "-f", "markdown", "-t", "odt", "-o", "-"]
            cmd.extend(extra_args)

            result = subprocess.run(
                cmd,
                input=content_with_footer.encode("utf-8"),
                capture_output=True,
                check=True,
            )

            odt_bytes = result.stdout

            if not odt_bytes:
                raise RuntimeError(
                    "Pandoc conversion failed - no output produced"
                )

            filename = self._generate_safe_filename(options.title)

            logger.info(
                f"Generated ODT in memory, size: {len(odt_bytes)} bytes"
            )

            return ExportResult(
                content=odt_bytes,
                filename=filename,
                mimetype=self.mimetype,
            )

        except subprocess.CalledProcessError as e:
            stderr = (
                e.stderr.decode("utf-8", errors="replace")
                if e.stderr
                else "unknown error"
            )
            logger.exception(f"Pandoc conversion failed: {stderr}")
            raise RuntimeError(f"Pandoc conversion failed: {stderr}") from e
        except Exception:
            logger.exception("Error generating ODT")
            raise

    def _add_footer(self, markdown_content: str) -> str:
        """Add LDR attribution footer to markdown content.

        Args:
            markdown_content: The original markdown text

        Returns:
            Markdown with footer appended
        """
        footer = (
            "\n\n---\n\n"
            "*Generated by [LDR - Local Deep Research]"
            "(https://github.com/LearningCircuit/local-deep-research) | "
            "Open Source AI Research Assistant*"
        )
        return markdown_content + footer

    def _sanitize_metadata(self, value: str) -> str:
        """Sanitize metadata value to prevent argument injection.

        Removes potential pandoc argument injection patterns from user-supplied
        metadata values.

        Args:
            value: The metadata value to sanitize

        Returns:
            Sanitized metadata value safe for pandoc arguments
        """
        # Remove potential argument injection patterns
        safe_value = value.replace("--", "").replace("\n", " ")
        return safe_value
