"""Gallery building and rendering logic."""

import shutil
from pathlib import Path
from typing import Any, Dict, Optional, Union

from jinja2 import Environment, FileSystemLoader, Template

from gallery.config import GalleryConfig
from gallery.utils.datetime_utils import (
    datetime_from_timestamp,
    strftime_filter,
)
from gallery.utils.metadata import (
    load_folder_metadata,
    merge_metadata,
    save_metadata_cache,
)
from gallery.utils.processing import (
    process_plot_files,
    render_gallery_page,
)


def get_template(template_dir: Optional[Union[Path, str]] = None):
    """
    Get the Jinja2 template for gallery rendering.

    Args:
        template_dir: Path to template directory. If None,
                     uses package default.

    Returns:
        Jinja2 Template object
    """
    if isinstance(template_dir, str):
        template_dir = Path(template_dir)

    if template_dir is None:
        # Use package-included template
        import gallery

        gallery_module_path = Path(gallery.__file__).parent
        template_dir = gallery_module_path / "templates"

    env = Environment(loader=FileSystemLoader(str(template_dir)))

    env.filters["datetime_from_timestamp"] = datetime_from_timestamp
    env.filters["strftime"] = strftime_filter

    return env.get_template("gallery.html")


def build_gallery(
    config: GalleryConfig,
    source_dir: Path,
    web_dir: Path,
    template: Optional[Template] = None,
    relative_path: Optional[Path] = None,
    inherited_metadata: Optional[Dict[str, Any]] = None,
) -> None:
    """
    Recursively build gallery structure from source directory.

    Processes all PDF files in the source directory, converts them to PNG,
    copies both to the web directory, and generates index.html files with
    navigation and thumbnails. Includes metadata support.

    Args:
        config: Gallery configuration object
        template: Jinja2 template for rendering
        source_dir: Source directory containing PDF files
        web_dir: Target web directory for gallery output
        relative_path: Relative path from gallery root (for navigation)
        inherited_metadata: Metadata inherited from parent directories
    """
    if not template:
        template = Template("./templates/gallery.html")
    if relative_path is None:
        relative_path = Path(".")

    if inherited_metadata is None:
        inherited_metadata = {}

    folder_metadata = load_folder_metadata(source_dir)
    current_metadata = merge_metadata(inherited_metadata, folder_metadata)

    # Find all plot files (both PDF and HTML)
    pdf_files = list(source_dir.glob("*.pdf"))
    html_files = list(source_dir.glob("*.html"))
    plot_files = pdf_files + html_files

    items = []
    plot_metadata_cache = {}

    # Process all plot files (PDFs and HTMLs)
    for plot_file in plot_files:
        item = process_plot_files(
            config=config,
            plot_file=plot_file,
            web_dir=web_dir,
            current_metadata=current_metadata,
        )
        items.append(item)
        plot_metadata_cache[plot_file.stem] = item["metadata"]

    if config.cache_enabled:
        save_metadata_cache(web_dir, plot_metadata_cache)

    # Process subdirectories
    subdirs = [d for d in source_dir.iterdir() if d.is_dir()]
    subdir_names = []
    for subdir in subdirs:
        subdir_web = web_dir / subdir.name
        subdir_web.mkdir(exist_ok=True)
        subdir_relative = relative_path / subdir.name
        build_gallery(
            config,
            subdir,
            subdir_web,
            template,
            subdir_relative,
            current_metadata if config.inherit_from_parent else {},
        )
        subdir_names.append(subdir.name)

    render_gallery_page(
        config=config,
        template=template,
        web_dir=web_dir,
        items=items,
        subdirs=subdir_names,
        relative_path=relative_path,
        metadata=current_metadata,
    )


def copy_assets(config: GalleryConfig, assets_src: Optional[Path] = None, verbose: bool = False) -> bool:
    """
    Copy assets to the web directory.

    Args:
        config: Gallery configuration object
        assets_src: Path to assets source. If None, uses package default.
        verbose: Whether to print status messages

    Returns:
        True if successful, False otherwise
    """
    try:
        if assets_src is None:
            # Use package-included assets
            import gallery

            gallery_module_path = Path(gallery.__file__).parent
            assets_src = gallery_module_path / "assets"

        if not assets_src.exists():
            if verbose:
                print(f"Warning: Assets directory {assets_src} not found")
            return False

        gallery_root = Path(config.web_folder) / config.plot_root
        assets_dst = gallery_root.parent / "assets"

        # Use the newest mtime across all source asset files as the staleness check,
        # so any change to any JS/CSS file triggers a redeploy.
        sentinel_dst = assets_dst / "css" / "main.css"
        newest_src_mtime = max(
            (f.stat().st_mtime for f in assets_src.rglob("*") if f.is_file()),
            default=0,
        )
        dst_mtime = sentinel_dst.stat().st_mtime if sentinel_dst.exists() else 0

        if not assets_dst.exists() or newest_src_mtime > (dst_mtime + 30):
            if assets_dst.exists():
                shutil.rmtree(assets_dst)
            shutil.copytree(assets_src, assets_dst)
            if verbose:
                print(f"Updated assets from {assets_src} to {assets_dst}")

        return True
    except Exception as e:
        if verbose:
            print(f"Warning: Could not copy assets: {e}")
        return False
