# manuscripta/export/book.py
import os
import shutil
import subprocess
import argparse
import yaml
import toml
import threading
import tempfile
from pathlib import Path
from manuscripta.enums.book_type import BookType
from manuscripta.export.validation import (
    validate_epub_with_epubcheck,
    validate_pdf,
    validate_markdown,
    validate_docx,
    validate_html,
)

# Replace with your data
DEFAULT_METADATA = """title: 'CHANGE TO YOUR TITLE'
author: 'YOUR NAME'
date: '2025'
lang: 'en'
"""

# All paths are relative to the current working directory (= book repo root).
# The CLI entry point is always invoked from the book repo root.
# No os.chdir() - the library must not change the process working directory.

# Define important directory and file paths
BOOK_DIR = "./manuscript"  # Location of markdown files organized by sections
OUTPUT_DIR = "./output"  # Output directory for compiled formats
BACKUP_DIR = "./output_backup"  # Backup location for previous output
# Set to None to derive from pyproject.toml automatically.
# Set a string to override the output file base name manually.
OUTPUT_FILE = ""
LOG_FILE = "export.log"  # Log file for script and Pandoc output/errors

# Supporting module paths (used via python -m instead of file paths)
_MOD_PATHS_TO_ABSOLUTE = "manuscripta.paths.to_absolute"
_MOD_PATHS_TO_RELATIVE = "manuscripta.paths.to_relative"
_MOD_PATHS_IMG_TAGS = "manuscripta.paths.img_tags"
_MOD_NORMALIZE_TOC = "manuscripta.markdown.normalize_toc"
TOC_FILE = Path(BOOK_DIR) / "front-matter" / "toc.md"

CONFIG_DIR = "./config"
METADATA_FILE = (
    Path(CONFIG_DIR) / "metadata.yaml"
)  # YAML file for Pandoc metadata (title, author, etc.)
EXPORT_SETTINGS_FILE = (
    Path(CONFIG_DIR) / "export-settings.yaml"
)  # YAML file for export configuration

# Supported output formats and their corresponding Pandoc targets
_BUILTIN_FORMATS = {
    "markdown": "gfm",  # GitHub-Flavored Markdown
    "pdf": "pdf",  # PDF format
    "epub": "epub",  # EPUB eBook format
    "docx": "docx",  # Microsoft Word format
    "html": "html",  # HTML format
}

# Built-in section orders (used as fallback when export-settings.yaml is missing)
_BUILTIN_DEFAULT_SECTION_ORDER = [
    "front-matter/toc.md",
    "front-matter/foreword.md",
    "front-matter/preface.md",
    "chapters",  # Entire chapters folder
    "back-matter/epilogue.md",
    "back-matter/glossary.md",
    "back-matter/appendix.md",
    "back-matter/acknowledgments.md",
    "back-matter/about-the-author.md",
    "back-matter/bibliography.md",
    "back-matter/imprint.md",
]

_BUILTIN_PAPERBACK_SECTION_ORDER = [
    "front-matter/toc-print.md",  # Your existing print TOC
    "front-matter/foreword.md",
    "front-matter/preface.md",
    "chapters",  # Entire chapters folder
    "back-matter/epilogue.md",
    "back-matter/glossary.md",
    "back-matter/appendix.md",
    "back-matter/acknowledgments.md",
    "back-matter/about-the-author.md",
    "back-matter/bibliography.md",
    "back-matter/imprint.md",
]

_BUILTIN_EPUB_SKIP_TOC_FILES = [
    "front-matter/toc.md",
    "front-matter/toc-print.md",
]

# Default TOC depth for auto-generated TOCs
# - Depth 2 (# ##): Recommended for most books, keeps TOC clean and navigable
# - Depth 3 (# ## ###): Good for technical/academic books with many subsections
# - Depth 1: Too shallow for most use cases
_BUILTIN_TOC_DEPTH = 2


# --- Config loading from export-settings.yaml --------------------------------


def load_export_settings(path=None):
    """
    Load export configuration from a YAML file.

    Returns the parsed dict, or {} if the file does not exist.
    """
    settings_path = Path(path) if path else EXPORT_SETTINGS_FILE
    if not settings_path.exists():
        return {}
    with settings_path.open("r", encoding="utf-8") as f:
        return yaml.safe_load(f)


def get_section_order_from_settings(settings, book_type_value):
    """
    Resolve the section order for a given book type from loaded settings.

    Fallback chain:
    - ebook   -> "ebook" key, then "default" key, then built-in default
    - paperback -> "paperback" key, then built-in paperback
    - hardcover -> "hardcover" key, then "paperback" key, then built-in paperback
    - audiobook -> "audiobook" key, then "default" key, then built-in default

    A null value in the YAML means "inherit from parent".
    Returns None if settings has no section_order at all (caller uses built-in).
    """
    orders = settings.get("section_order")
    if not orders:
        return None

    order = orders.get(book_type_value)

    # null fallback chain
    if order is None:
        if book_type_value in ("ebook", "audiobook"):
            order = orders.get("default")
        elif book_type_value == "hardcover":
            order = orders.get("paperback")

    return order


# --- Load settings and populate module-level constants -----------------------

_EXPORT_SETTINGS = load_export_settings()

FORMATS = _EXPORT_SETTINGS.get("formats", _BUILTIN_FORMATS)
DEFAULT_TOC_DEPTH = _EXPORT_SETTINGS.get("toc_depth", _BUILTIN_TOC_DEPTH)
EPUB_SKIP_TOC_FILES = _EXPORT_SETTINGS.get(
    "epub_skip_toc_files", _BUILTIN_EPUB_SKIP_TOC_FILES
)

# Section orders: prefer config, fall back to built-in
DEFAULT_SECTION_ORDER = (
    get_section_order_from_settings(_EXPORT_SETTINGS, "default")
    or _BUILTIN_DEFAULT_SECTION_ORDER
)
EBOOK_SECTION_ORDER = (
    get_section_order_from_settings(_EXPORT_SETTINGS, "ebook") or DEFAULT_SECTION_ORDER
)
PAPERBACK_SECTION_ORDER = (
    get_section_order_from_settings(_EXPORT_SETTINGS, "paperback")
    or _BUILTIN_PAPERBACK_SECTION_ORDER
)
HARDCOVER_SECTION_ORDER = (
    get_section_order_from_settings(_EXPORT_SETTINGS, "hardcover")
    or PAPERBACK_SECTION_ORDER
)


def pick_section_order(book_type: "BookType", fmt: str) -> list[str]:
    """
    Decide which section order to use if --order was not provided.
    - ebook  -> EBOOK_SECTION_ORDER
    - paperback/hardcover -> PAPERBACK/HARDCOVER_SECTION_ORDER
    Note: For non-EPUB builds of ebook (e.g., markdown or pdf drafts), we still
    stick to EBOOK_SECTION_ORDER unless user overrides.
    """
    if book_type.value == "ebook":
        return EBOOK_SECTION_ORDER
    if book_type.value == "paperback":
        return PAPERBACK_SECTION_ORDER
    if book_type.value == "hardcover":
        return HARDCOVER_SECTION_ORDER
    # Fallback
    return DEFAULT_SECTION_ORDER


def resolve_ext(fmt: str, custom_markdown_ext: str | None) -> str:
    if fmt == "markdown":
        return custom_markdown_ext if custom_markdown_ext else "md"
    return FORMATS[fmt]


def get_project_name_from_pyproject(pyproject_path="pyproject.toml"):
    """
    Extract the project name from the pyproject.toml file.

    This function reads the `[tool.poetry.name]` field from a pyproject.toml file
    and returns it as a string. This value is used as the base prefix for output filenames.

    Parameters:
    - pyproject_path (str): Path to the pyproject.toml file (default: "pyproject.toml")

    Returns:
    - str: The project name if found, otherwise a fallback value ("book")
    """
    if pyproject_path is None:
        pyproject_path = Path(__file__).resolve().parent.parent / "pyproject.toml"
    try:
        data = toml.load(pyproject_path)
        return (
            data.get("tool", {}).get("poetry", {}).get("name")
            or data.get("project", {}).get("name")
            or "book"
        )
    except Exception as e:
        print(f"⚠️ Could not read project name from {pyproject_path}: {e}")
        return "book"


def get_metadata_language():
    """Read and return the 'lang' field from metadata.yaml if present, else return None."""
    if not METADATA_FILE.exists():
        print(f"⚠️ Metadata file not found at: {METADATA_FILE}")
        return None
    with METADATA_FILE.open("r", encoding="utf-8") as f:
        try:
            metadata = yaml.safe_load(f)
            return metadata.get("language") or metadata.get("lang")
        except yaml.YAMLError as e:
            print(f"⚠️ Failed to parse {METADATA_FILE}: {e}")
            return None


def run_script(module_path, arg=None):
    """Run a manuscripta module with optional arguments and log output."""
    try:
        cmd = ["python3", "-m", module_path]
        if arg:
            cmd.append(arg)
        subprocess.run(
            cmd, check=True, stdout=open(LOG_FILE, "a"), stderr=open(LOG_FILE, "a")
        )
        print(f"Successfully executed: {module_path} {arg if arg else ''}")
    except subprocess.CalledProcessError as e:
        print(f"Error running module {module_path}: {e}")
        raise  # Needed so tests detect the failure


def prepare_output_folder(verbose=False):
    """
    Prepares the output directory by ensuring it's empty.
    - Deletes existing backup dir if present
    - Moves current output dir to backup
    - Creates a fresh output dir
    """
    if os.path.exists(BACKUP_DIR):
        shutil.rmtree(BACKUP_DIR)
        if verbose:
            print("📦 Deleted old backup directory.")

    if os.path.exists(OUTPUT_DIR) and os.listdir(OUTPUT_DIR):
        shutil.move(OUTPUT_DIR, BACKUP_DIR)
        if verbose:
            print("📁 Moved current output to backup directory.")

    os.makedirs(OUTPUT_DIR, exist_ok=True)
    if verbose:
        print("📂 Created clean output directory.")


def get_or_create_metadata_file(preferred_path: Path | str | None = None):
    """
    Return a usable metadata file path.

    - If the preferred_path exists, return it with `is_temp=False`.
    - Otherwise, create a temporary metadata YAML file with default content
      and return it with `is_temp=True`.
    """
    path = Path(preferred_path) if preferred_path else METADATA_FILE
    if path.exists():
        return path, False

    tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".yaml")
    tmp.write(DEFAULT_METADATA.encode("utf-8"))
    tmp.flush()
    tmp.close()
    return Path(tmp.name), True


def ensure_metadata_file():
    """
    Ensures the metadata file exists.
    - Prevents Pandoc warnings by providing minimal metadata if missing.
    """
    if not os.path.exists(METADATA_FILE):
        print(f"⚠️ Metadata file missing! Creating default {METADATA_FILE}.")
        os.makedirs(os.path.dirname(METADATA_FILE), exist_ok=True)
        with open(METADATA_FILE, "w", encoding="utf-8") as f:
            # TODO: Replace with your data
            f.write(
                'title: "CHANGE TO YOUR TITLE"\n'
                'author: "YOUR NAME"\n'
                'date: "2025"\n'
                'lang: "en"\n'
            )


def filter_section_order_for_epub(section_order: list[str]) -> list[str]:
    """
    Remove manual TOC files from section order for EPUB ebook builds.

    Pandoc will generate the TOC automatically with the --toc flag,
    which creates proper cross-file links (chXXX.xhtml#anchor) that
    pass epubcheck validation.

    Note: This is only used for ebook EPUBs. Paperback/hardcover EPUBs
    use the existing toc-print.md file.
    """
    filtered = [s for s in section_order if s not in EPUB_SKIP_TOC_FILES]
    return filtered


def compile_book(
    format,
    section_order,
    book_type,
    cover_path=None,
    force_epub2=False,
    lang="en",
    custom_ext=None,
    toc_depth=DEFAULT_TOC_DEPTH,
    use_manual_toc=False,
):
    """
    Compiles the book into a specific format using Pandoc.

    Parameters:
    - format: Format to compile (e.g. pdf, docx, epub)
    - section_order: Ordered list of sections to include
    - book_type: BookType enum (ebook, paperback, hardcover)
    - cover_path: Optional path to cover image (for EPUB)
    - force_epub2: Force EPUB 2 format
    - lang: Language code (e.g. en, de, fr)
    - custom_ext: Custom file extension for markdown output
    - toc_depth: Depth of auto-generated TOC (default: 2)
    - use_manual_toc: Use existing toc.md instead of auto-generating for EPUB
    """
    ext = resolve_ext(format, custom_ext)
    output_path = os.path.join(OUTPUT_DIR, f"{OUTPUT_FILE}.{ext}")

    # Determine if this is a print build (paperback/hardcover)
    is_print_build = book_type.value in ("paperback", "hardcover")

    # For EPUB + ebook only: filter out manual TOC files (Pandoc generates TOC automatically)
    # Unless --use-manual-toc is set, then use your existing toc.md
    # For EPUB + paperback/hardcover: use your existing toc-print.md
    if format == "epub" and not is_print_build and not use_manual_toc:
        effective_order = filter_section_order_for_epub(section_order)
        if len(effective_order) < len(section_order):
            print(
                "ℹ️  EPUB (ebook): Skipping manual TOC. Pandoc will generate TOC automatically."
            )
    elif format == "epub" and not is_print_build and use_manual_toc:
        effective_order = section_order
        print("ℹ️  EPUB (ebook): Using your existing toc.md (--use-manual-toc).")
    else:
        # PDF, DOCX, HTML, Markdown, or EPUB for print: use your existing files unchanged
        effective_order = section_order

    md_files = []

    # Gather markdown files from the specified order
    for section in effective_order:
        section_path = os.path.join(BOOK_DIR, section)
        if os.path.isdir(section_path):
            # Include all .md files in directory, sorted
            md_files.extend(
                sorted(
                    os.path.join(section_path, f)
                    for f in os.listdir(section_path)
                    if f.endswith(".md")
                )
            )
        elif os.path.isfile(section_path):
            # Include specific markdown file
            md_files.append(section_path)

    if not md_files:
        print(f"❌ No Markdown files found for format {format}. Skipping.")
        return

    # Construct Pandoc command
    pandoc_cmd = [
        "pandoc",
        "--verbose",
        "--from=markdown",
        f"--to={FORMATS[format]}",
        f"--output={output_path}",
        f"--resource-path={os.path.abspath('./assets')}",  # To resolve images and assets
        f"--metadata-file={METADATA_FILE}",
    ] + md_files  # Append all markdown files to compile

    # EPUB-specific options
    if format == "epub":
        pandoc_cmd.extend(["--metadata", f"lang={lang}"])
        # Only auto-generate TOC for ebook type when --use-manual-toc is NOT set
        if not is_print_build and not use_manual_toc:
            pandoc_cmd.extend(
                [
                    "--toc",  # Generate table of contents
                    f"--toc-depth={toc_depth}",  # TOC depth (default: 2)
                    "--epub-chapter-level=1",  # Each H1 becomes a new XHTML file
                ]
            )
        if force_epub2:
            pandoc_cmd.extend(["--metadata", "epub.version=2"])
        if cover_path:
            pandoc_cmd.append(f"--epub-cover-image={cover_path}")

    # PDF-specific options
    if format == "pdf":
        pandoc_cmd.extend(
            [
                "--pdf-engine=xelatex",  # Options: xelatex, lualatex, pdflatex
                "-V",
                "mainfont=DejaVu Sans",
                "-V",
                "monofont=DejaVu Sans Mono",
            ]
        )

    # Markdown-specific options
    if format == "markdown":
        pandoc_cmd.append("--wrap=none")  # Prevent line breaks in links and paragraphs

    # HTML-specific options
    if format == "html":
        pandoc_cmd.extend(
            [
                "--standalone",  # Generate complete HTML document
                "--css=assets/style.css",  # Optional: Include CSS file (must exist)
                "--metadata",
                f"lang={lang}",
            ]
        )

    # Run Pandoc and log output
    try:
        with open(LOG_FILE, "a") as log_file:
            subprocess.run(pandoc_cmd, check=True, stdout=log_file, stderr=log_file)
        print(f"✅ Successfully generated: {output_path}")
    except subprocess.CalledProcessError as e:
        print(f"❌ Error compiling {format}: {e}")


def normalize_toc_if_needed(toc_path: Path, args):
    """
    Normalize TOC links (only for web/ebook ToC 'toc.md').

    This step is mainly for non-EPUB/non-print formats where the manual
    TOC is included in the output.
    """
    try:
        if toc_path.exists() and toc_path.name == "toc.md":
            toc_mode = "strip-to-anchors"
            toc_ext = args.extension if args.extension else "md"
            subprocess.run(
                [
                    "python3", "-m", _MOD_NORMALIZE_TOC,
                    "--toc",
                    str(toc_path),
                    "--mode",
                    toc_mode,
                    "--ext",
                    toc_ext,
                ],
                check=True,
                stdout=open(LOG_FILE, "a"),
                stderr=open(LOG_FILE, "a"),
            )
            print(f"✅ TOC normalized using mode={toc_mode}: {toc_path}")
        else:
            print(f"ℹ️  Skipping TOC normalization for {toc_path.name} (not ebook toc).")
    except subprocess.CalledProcessError as e:
        print(f"❌ Error normalizing TOC: {e}")


def main():
    """Main script execution logic."""
    parser = argparse.ArgumentParser(
        description="Export your book into multiple formats."
    )
    parser.add_argument(
        "--format", type=str, help="Specify formats (comma-separated, e.g., pdf,epub)."
    )
    parser.add_argument(
        "--order",
        type=str,
        default=None,
        help="Specify document order (comma-separated). If omitted, a sane default is chosen based on --book-type.",
    )
    parser.add_argument(
        "--cover", type=str, help="Optional path to cover image (for EPUB export)."
    )
    parser.add_argument(
        "--epub2",
        action="store_true",
        help="Force EPUB 2 export (for epubli compatibility).",
    )
    parser.add_argument(
        "--lang", type=str, help="Language code for metadata (e.g. en, de, fr)"
    )
    parser.add_argument(
        "--extension",
        type=str,
        help="Custom file extension for markdown export (default: md)",
    )
    parser.add_argument(
        "--book-type",
        type=str,
        choices=[bt.value for bt in BookType],
        default=BookType.EBOOK.value,
        help="Specify the book type (ebook, paperback, hardcover). Affects TOC generation and output naming.",
    )
    parser.add_argument(
        "--output-file",
        type=str,
        help="Custom output file base name (overrides project name)",
    )
    parser.add_argument(
        "--no-type-suffix",
        action="store_true",
        help="Do not append '-{book_type}' to the output base name.",
    )
    parser.add_argument(
        "--toc-depth",
        type=int,
        default=DEFAULT_TOC_DEPTH,
        help=f"Depth of auto-generated TOC for EPUB and print PDF (default: {DEFAULT_TOC_DEPTH}). "
        "Use 2 for most books, 3 for technical books with many subsections.",
    )
    parser.add_argument(
        "--use-manual-toc",
        action="store_true",
        help="Use your existing toc.md instead of auto-generating TOC for EPUB ebook.",
    )

    parser.add_argument(
        "--copy-epub-to",
        type=str,
        nargs="?",
        const="~/Downloads",
        default=None,
        help="Copy the generated EPUB file to the specified directory (default: ~/Downloads). "
        "Use without value for ~/Downloads, or provide a custom path.",
    )

    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "--skip-images",
        action="store_true",
        help="Skip all image-related steps (no path rewrites, no tag transforms).",
    )
    group.add_argument(
        "--keep-relative-paths",
        action="store_true",
        help="Do not rewrite image/URL paths to absolute and back; keeps relative paths (skips Steps 1 and 4).",
    )

    args = parser.parse_args()

    # Log --copy-epub-to early so user sees it was recognized
    if args.copy_epub_to:
        resolved_dest = Path(args.copy_epub_to).expanduser().resolve()
        print(f"📋 EPUB copy requested -> {resolved_dest}")

    # Book type handling
    book_type = BookType(args.book_type)

    # Decide section order: CLI > auto by book type
    if args.order:
        section_order = args.order.split(",")
    else:
        # We'll pick later per format to allow mixed builds like: --format=epub,pdf
        section_order = None

    # Set global output filename
    global OUTPUT_FILE
    add_type_suffix = not args.no_type_suffix
    if args.output_file:
        # User provided name: use the stem, extension is added per-format later
        op = Path(args.output_file)
        OUTPUT_FILE = op.stem
    elif OUTPUT_FILE is None or OUTPUT_FILE == "":
        # Fall back to project name
        project_name = get_project_name_from_pyproject()
        OUTPUT_FILE = project_name

    if add_type_suffix:
        OUTPUT_FILE = f"{OUTPUT_FILE}_{book_type.value}"

    print(f"📘 Output file base name set to: {OUTPUT_FILE}")

    # Determine language: CLI > metadata.yaml > fallback
    metadata_lang = get_metadata_language()
    cli_lang = args.lang

    if cli_lang:
        if metadata_lang and cli_lang != metadata_lang:
            print("\n⚠️⚠️⚠️ LANGUAGE MISMATCH DETECTED ⚠️⚠️⚠️")
            print(
                f"Metadata file says: '{metadata_lang}' but CLI argument is: '{cli_lang}'"
            )
            print("Using CLI argument value.\n")
        lang = cli_lang
    elif metadata_lang:
        lang = metadata_lang
        print(f"🌐 Using language from metadata.yaml: '{lang}'")
    else:
        print(f"cli_lang: '{cli_lang}'")
        lang = "en"
        print("⚠️ No language set in CLI or metadata.yaml. Defaulting to 'en'")

    # Step 1a: Normalize TOC (for non-EPUB/non-print formats where manual TOC is used)
    # Note: For EPUB and print PDF, the manual TOC is skipped anyway
    try:
        if TOC_FILE.exists():
            toc_mode = "strip-to-anchors"
            toc_ext = args.extension if args.extension else "md"
            subprocess.run(
                [
                    "python3", "-m", _MOD_NORMALIZE_TOC,
                    "--toc",
                    str(TOC_FILE),
                    "--mode",
                    toc_mode,
                    "--ext",
                    toc_ext,
                ],
                check=True,
                stdout=open(LOG_FILE, "a"),
                stderr=open(LOG_FILE, "a"),
            )
            print(f"✅ TOC normalized using mode={toc_mode}")
        else:
            print(f"ℹ️  No TOC file at {TOC_FILE}; skipping TOC normalization.")
    except subprocess.CalledProcessError as e:
        print(f"❌ Error normalizing TOC: {e}")

    # Step 1: Convert image paths to absolute
    # Run pre-processing scripts unless user opts out or wants to keep relative paths
    if not args.skip_images and not args.keep_relative_paths:
        run_script(_MOD_PATHS_TO_ABSOLUTE)  # Convert relative paths to absolute
        run_script(_MOD_PATHS_IMG_TAGS, "--to-absolute")  # Process image tags
    elif args.skip_images:
        print("⏭️  Skipping Step 1 (skip-images).")
    else:
        print("⏭️  Skipping Step 1 (keep relative paths).")

    # Step 2: Prepare environment
    prepare_output_folder()  # Prepare folders and backup if needed
    global METADATA_FILE
    METADATA_FILE, _is_temp_metadata = get_or_create_metadata_file(
        METADATA_FILE
    )  # Make sure metadata exists

    # Step 3: Compile the book in requested formats
    selected_formats = args.format.split(",") if args.format else FORMATS.keys()

    for fmt in selected_formats:
        if fmt not in FORMATS:
            print(f"⚠️ Skipping unknown format: {fmt}")
            continue

        effective_order = (
            section_order
            if section_order is not None
            else pick_section_order(book_type, fmt)
        )

        # Warning if print TOC file is missing (only relevant for non-auto-TOC builds)
        if "front-matter/toc-print.md" in effective_order:
            toc_print_path = Path(BOOK_DIR) / "front-matter" / "toc-print.md"
            if not toc_print_path.exists():
                print(
                    "⚠️ Print ToC file missing: manuscript/front-matter/toc-print.md "
                    "(will use auto-generated TOC instead)"
                )
                # Remove the missing file from order
                idx = effective_order.index("front-matter/toc-print.md")
                effective_order = effective_order.copy()
                effective_order.pop(idx)

        # TOC normalization only for formats that use manual TOC
        # (EPUB and print PDF use auto-generated TOC, so this is skipped for them)
        if fmt not in ("epub",) and not (
            fmt == "pdf" and book_type.value in ("paperback", "hardcover")
        ):
            toc_candidate = (
                Path(BOOK_DIR)
                / "front-matter"
                / (
                    "toc.md"
                    if "front-matter/toc.md" in effective_order
                    else "toc-print.md"
                )
            )
            if toc_candidate.exists():
                normalize_toc_if_needed(toc_candidate, args)

        compile_book(
            fmt,
            effective_order,
            book_type,
            args.cover,
            args.epub2,
            lang,
            args.extension,
            args.toc_depth,
            args.use_manual_toc,
        )

    # Step 4: Restore original image paths
    # Revert any image/URL changes made before compilation unless we kept relative paths
    if not args.skip_images and not args.keep_relative_paths:
        run_script(_MOD_PATHS_TO_RELATIVE)  # Convert absolute paths back to relative
        run_script(_MOD_PATHS_IMG_TAGS, "--to-relative")  # Revert image tag changes
    elif args.skip_images:
        print("⏭️  Skipping Step 4 (skip-images).")
    else:
        print("⏭️  Skipping Step 4 (keep relative paths).")

    # Step 5: Start background validation for each generated format
    threads = []

    for fmt in selected_formats:
        ext_for_fmt = resolve_ext(fmt, args.extension if fmt == "markdown" else None)
        output_path = os.path.join(OUTPUT_DIR, f"{OUTPUT_FILE}.{ext_for_fmt}")

        if fmt == "epub":
            thread = threading.Thread(
                target=validate_epub_with_epubcheck,
                args=(output_path,),
                name=f"Validate-{fmt.upper()}",
                daemon=False,
            )
            print("🧩 EPUB generated. Validation running in background...")
        elif fmt == "pdf":
            thread = threading.Thread(
                target=validate_pdf,
                args=(output_path,),
                name=f"Validate-{fmt.upper()}",
                daemon=False,
            )
            print("🧩 PDF generated. Validation running in background...")
        elif fmt == "docx":
            thread = threading.Thread(
                target=validate_docx,
                args=(output_path,),
                name=f"Validate-{fmt.upper()}",
                daemon=False,
            )
            print("🧩 DOCX generated. Validation running in background...")
        elif fmt == "markdown":
            thread = threading.Thread(
                target=validate_markdown,
                args=(output_path,),
                name=f"Validate-{fmt.upper()}",
                daemon=False,
            )
            print("🧩 Markdown generated. Validation running in background...")
        elif fmt == "html":
            thread = threading.Thread(
                target=validate_html,
                args=(output_path,),
                name="Validate-HTML",
                daemon=False,
            )
            print("🧩 HTML generated. Validation running in background...")
        else:
            continue  # Skip unknown formats

        thread.start()
        threads.append(thread)

    # Step 5b: Copy EPUB to target directory if requested
    if args.copy_epub_to:
        epub_output = Path(OUTPUT_DIR) / f"{OUTPUT_FILE}.epub"
        epub_output_abs = epub_output.resolve()
        print(f"📋 Looking for EPUB: {epub_output_abs}")

        if epub_output_abs.is_file():
            target_dir = Path(args.copy_epub_to).expanduser().resolve()
            target_path = target_dir / epub_output.name
            try:
                target_dir.mkdir(parents=True, exist_ok=True)
                shutil.copy2(epub_output_abs, target_path)
                print(f"✅ EPUB copied to: {target_path}")
            except OSError as e:
                print(f"❌ Failed to copy EPUB to {target_dir}: {e}")
        else:
            print(f"⚠️ EPUB not found at {epub_output_abs}, nothing to copy.")
            if "epub" not in selected_formats:
                print(
                    f"   Hint: EPUB was not in the selected formats ({', '.join(selected_formats)}). "
                    "Use --format epub or a target that includes EPUB."
                )

    # Final messages
    print("\n🚀 Export completed. Background validation in progress...")
    print("📁 Outputs: ./output/")
    print("📄 Logs: ./export.log")
    print("🔍 Validation results will appear shortly.")

    if _is_temp_metadata:
        try:
            METADATA_FILE.unlink(missing_ok=True)
            print(f"🗑️ Deleted temporary metadata file: {METADATA_FILE}")
        except OSError as e:
            print(f"⚠️ Could not delete temporary metadata file {METADATA_FILE}: {e}")


# Entry point
if __name__ == "__main__":
    main()
