"""PDF tools — merge, split, compress, rotate, encrypt, and more."""

from __future__ import annotations

import base64
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mcp.server.fastmcp import FastMCP


def _b64(data: bytes) -> str:
    return base64.b64encode(data).decode("ascii")


def _raw(b64: str) -> bytes:
    return base64.b64decode(b64)


def register(mcp: FastMCP) -> None:
    from peasy_pdf import engine

    @mcp.tool()
    def pdf_merge(files_b64: list[str]) -> str:
        """Merge multiple PDFs into one.

        files_b64: List of base64-encoded PDF files.
        Returns: Base64-encoded merged PDF.
        """
        return _b64(engine.merge(*[_raw(f) for f in files_b64]))

    @mcp.tool()
    def pdf_split(file_b64: str, ranges: str = "", every: int = 0) -> list[str]:
        """Split a PDF into parts.

        file_b64: Base64-encoded PDF.
        ranges: Comma-separated ranges like '1-3,4-6'.
        every: Split every N pages.
        Returns: List of base64-encoded PDF parts.
        """
        return [_b64(p) for p in engine.split(_raw(file_b64), ranges=ranges, every=every)]

    @mcp.tool()
    def pdf_rotate(file_b64: str, angle: int = 90, pages: str = "all") -> str:
        """Rotate pages in a PDF.

        file_b64: Base64-encoded PDF.
        angle: Rotation angle (90, 180, 270).
        pages: Page spec like '1,3,5-7' or 'all'.
        Returns: Base64-encoded rotated PDF.
        """
        return _b64(engine.rotate(_raw(file_b64), angle=angle, pages=pages))

    @mcp.tool()
    def pdf_compress(file_b64: str) -> str:
        """Compress a PDF to reduce file size.

        file_b64: Base64-encoded PDF.
        Returns: Base64-encoded compressed PDF.
        """
        return _b64(engine.compress(_raw(file_b64)))

    @mcp.tool()
    def pdf_extract_text(file_b64: str, pages: str = "all") -> str:
        """Extract text from a PDF.

        file_b64: Base64-encoded PDF.
        pages: Page spec like '1-3' or 'all'.
        Returns: Extracted text.
        """
        return engine.extract_text(_raw(file_b64), pages=pages).full_text

    @mcp.tool()
    def pdf_info(file_b64: str) -> dict[str, object]:
        """Get PDF information (page count, metadata, size).

        file_b64: Base64-encoded PDF.
        Returns: Dict with pages, encrypted, title, author, etc.
        """
        r = engine.info(_raw(file_b64))
        return {
            "pages": r.pages,
            "encrypted": r.encrypted,
            "title": r.title,
            "author": r.author,
            "subject": r.subject,
            "size_bytes": r.size_bytes,
        }

    @mcp.tool()
    def pdf_metadata(
        file_b64: str,
        title: str | None = None,
        author: str | None = None,
        subject: str | None = None,
        keywords: str | None = None,
    ) -> str:
        """Set PDF metadata. Returns base64-encoded PDF with updated metadata."""
        return _b64(
            engine.set_metadata(
                _raw(file_b64), title=title, author=author, subject=subject, keywords=keywords
            )
        )

    @mcp.tool()
    def pdf_encrypt(file_b64: str, password: str) -> str:
        """Encrypt a PDF with password protection.

        Returns: Base64-encoded encrypted PDF.
        """
        return _b64(engine.encrypt(_raw(file_b64), user_password=password))

    @mcp.tool()
    def pdf_decrypt(file_b64: str, password: str) -> str:
        """Decrypt a password-protected PDF.

        Returns: Base64-encoded decrypted PDF.
        """
        return _b64(engine.decrypt(_raw(file_b64), password=password))

    @mcp.tool()
    def pdf_delete_pages(file_b64: str, pages: str) -> str:
        """Delete specific pages from a PDF.

        pages: Page spec like '2,5-7'.
        Returns: Base64-encoded PDF with pages removed.
        """
        return _b64(engine.delete_pages(_raw(file_b64), pages=pages))

    @mcp.tool()
    def pdf_reverse(file_b64: str) -> str:
        """Reverse the page order of a PDF.

        Returns: Base64-encoded reversed PDF.
        """
        return _b64(engine.reverse(_raw(file_b64)))
