"""Static build of a website using kdlj2."""

import json
import os
import re
import shutil
from typing import Any

import jinja2

from kdlj2_web.render import render_template


def ensure_dist_folder(src_path: str = "", dist_path: str = "dist") -> None:
    """Make sure the dist folder exists before exporting static built files to it."""
    dist_path = os.path.join(".", src_path, dist_path)

    if os.path.exists(dist_path):
        shutil.rmtree(dist_path)

    os.makedirs(dist_path)

    static_src = os.path.join(".", src_path, "static")
    if os.path.exists(static_src):
        shutil.copytree(static_src, os.path.join(dist_path, "static"))


def list_all_pages(src_path: str = "") -> list[str]:
    """Return all pages in the source tree."""
    pages = []
    template_dir = os.path.join(src_path, "templates")

    for file in os.listdir(template_dir):
        if file.endswith(".kdl.j2") and not file.startswith(("_", ".")):
            with open(os.path.join(template_dir, file), "r") as f:
                first_line = f.readline()
                webmode_match: re.Match[str] | None = re.match(
                    r"{#\s*webmode:\s*(\w+)\s*#}", first_line
                )
                webmode: str = webmode_match.group(1) if webmode_match else "default"

                if webmode == "debug":
                    continue

            pages.append(file.replace(".kdl.j2", ""))

    return pages


def static_build(
    env: jinja2.Environment,
    src_path: str = "",
    dist_path: str = "dist",
    custom_opts: dict[str, Any] | None = None,
) -> None:
    """
    Execute a static build from a source path to a destination path.

    Uses a passed Jinja environment, supports custom options.
    """
    ensure_dist_folder(dist_path)

    with open("options.json") as opts_file:
        build_data = json.load(opts_file)

    pages = list_all_pages()

    for page in pages:
        print(f"  -> Generating {page}.html...")
        html = render_template(
            env, page, {**build_data, "debug": False, **(custom_opts or {})}
        )

        if isinstance(html, str):
            with open(os.path.join(dist_path, f"{page}.html"), "w") as f:
                f.write(html)
        else:
            print(f"  [!] Failed to build {page}: {html[1]}")
