# src/chitai/services/filesystem_library.py

from pathlib import Path
import re

from jinja2 import Template
from advanced_alchemy.service import ModelDictT

import chitai.database.models as m

# TODO: Replace Jinja2 templates with a simpler custom templating system.
# Current Jinja2 implementation is overly complex for basic path generation.
# Consider a simpler approach:
#   - Use simple placeholder syntax: {author}/{series}/{series_position} - {title}
#   - Support only essential variables: {author}, {series}, {series_position}, {title}, {isbn}
#   - Auto-handle missing values (e.g., skip {series}/ if series is empty)


default_path_template = """
/{{book.authors[0] if book.authors else 'Unknown'}}
{%- if book.series -%}
/{{book.series}}
{%- endif -%}
{%- if book.series_position -%}
{%- set formatted_position = '{:04.1f}'.format(book.series_position|float) -%}
/{{formatted_position.rstrip('0').rstrip('.')}} - {{book.title}}
{%- else %}/{{book.title}}
{% endif -%}
"""


class BookPathGenerator:
    """
    Generates organized filesystem paths for books based on customizable Jinja2 templates.

    Uses book metadata (author, series, title, etc.) to organize books into a hierarchical
    directory structure. Supports separate templates for the directory path and filename.

    """

    def __init__(
        self,
        root_path: Path | str,
        path_template: str = default_path_template,
        filename_template: str | None = None,
    ) -> None:
        """
        Initialize the path generator with templates.

        Args:
            root_path: The base filesystem path where books will be organized.
            path_template: Jinja2 template string for directory structure.
                          Default organizes by author, series, and title.
            filename_template: Optional Jinja2 template for custom filenames.
                              If None, original filenames are preserved.
        """
        self.root_path = Path(root_path)
        self.path_template: Template = Template(path_template)
        self.filename_template = (
            Template(filename_template) if filename_template else None
        )

    def generate_full_path(self, book_data: dict, filename: Path | str) -> Path:
        """
        Generate the complete filesystem path including directory structure and filename.

        Combines the generated book directory path with the generated filename to produce
        the full path where a book file should be stored. This is the complete path
        relative to the generator's root path.

        Args:
            book_data: Dictionary containing book metadata (author, title, series, etc.).
            filename: The original filename or Path object to transform.

        Returns:
            Complete relative Path including directory structure and filename.
        """

        return self.generate_path(book_data) / self.generate_filename(
            book_data, filename
        )

    def generate_path(self, book_data: dict) -> Path:
        """
        Generate the organized directory path for a book based on its metadata.

        Uses the path template to create a hierarchical structure. Handles edge cases like
        missing authors (defaults to 'Unknown'), optional series information, and series
        position formatting. Sanitizes the result by removing consecutive slashes and
        unnecessary whitespace.

        Args:
            book_data: Dictionary containing book metadata with keys like:
                      - authors: List of author names
                      - series: Series name (optional)
                      - series_position: Position in series (optional)
                      - title: Book title

        Returns:
            Cleaned Path object relative to the generator's root path.

        """

        result = self.root_path / Path(self.path_template.render(book=book_data))

        # Clean up
        result = re.sub(r"/+", "/", str(result))  # Remove consecutive backslashes
        result = re.sub(r"/\s+", "/", result)  # Remove whitespace after backslashes
        return Path(result.strip())

    def generate_filename(self, book_data: dict, filename: Path | str) -> Path:
        """
        Generate or transform a filename based on book metadata.

        If a filename template is configured, uses it to generate a custom filename
        based on book metadata. Otherwise, returns the original filename unchanged.

        Args:
            book_data: Dictionary containing book metadata.
            filename: The original filename or Path object to transform.

        Returns:
            The generated or original filename as a Path object.

        Raises:
            jinja2.TemplateError: If the filename template contains invalid Jinja2 syntax.

        """
        filename = Path(filename)

        # TODO: Implement a filename template.
        # For now just returns the original filename
        if self.filename_template:
            ...
        return Path(filename)
