# mkdocs_vwidalias/plugin.py
from __future__ import annotations
import os
import re
from pathlib import Path
from typing import Dict, Optional

from mkdocs.plugins import BasePlugin
from mkdocs.config import config_options
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.nav import Navigation
from mkdocs.utils import write_file
import logging

log = logging.getLogger("mkdocs.plugins.vwidalias")

VALID_HTML_ID = re.compile(r"^[A-Za-z][\w\-\:\.]*$")

def normalize_id(raw: str) -> Optional[str]:
    """Normalize and validate a front-matter ID value."""
    if not raw:
        return None
    raw = str(raw).strip()
    raw = re.sub(r"\s+", "-", raw)  # spaces -> hyphens
    if not VALID_HTML_ID.match(raw):
        return None
    return raw

REDIRECT_TEMPLATE = """<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Redirecting…</title>
    <meta http-equiv="refresh" content="0; url=/{target}">
    <link rel="canonical" href="/{target}">
    <script>location.replace("/{target}");</script>
    <style>body{{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;padding:2rem}}</style>
  </head>
  <body>
    <p>Redirecting to <a href="/{target}">/{target}</a>…</p>
  </body>
</html>
"""

class MkdocsVwidaliasPlugin(BasePlugin):
    """
    mkdocs_vwidalias:
    Generates alias pages at /<ID>/index.html (or /<prefix>/<ID>/index.html)
    for pages containing a front-matter 'id' (configurable).
    Each alias redirects to the page with '#<ID>' appended by default.
    """

    config_scheme = (
        ("id_field", config_options.Type(str, default="id")),
        ("alias_prefix", config_options.Type(str, default="")),
        ("append_hash", config_options.Type(bool, default=True)),
        ("fail_on_duplicate", config_options.Type(bool, default=False)),
    )

    def __init__(self):
        super().__init__()
        self._site_dir: Optional[str] = None
        self._map: Dict[str, str] = {}

    def on_config(self, config: MkDocsConfig, **kwargs):
        self._site_dir = config.site_dir
        log.info("[mkdocs_vwidalias] Initialized. site_dir=%s", self._site_dir)
        return config

    def on_nav(self, nav: Navigation, config: MkDocsConfig, files, **kwargs):
        seen = {}
        for page in nav.pages:
            meta = getattr(page, "meta", {}) or {}
            raw_id = meta.get(self.config["id_field"])
            html_id = normalize_id(raw_id) if raw_id else None
            if not html_id:
                continue

            page_url = page.url or ""
            if page_url.endswith(".html"):
                page_url = page_url[:-5]
            if not page_url.endswith("/"):
                page_url += "/"

            target = page_url
            if self.config["append_hash"]:
                target = f"{page_url}#{html_id}"

            if html_id in seen:
                msg = (f"[mkdocs_vwidalias] Duplicate id '{html_id}' "
                       f"on pages: {seen[html_id]} and {page.file.src_path}")
                if self.config["fail_on_duplicate"]:
                    raise ValueError(msg)
                else:
                    log.warning(msg)
                    continue

            seen[html_id] = page.file.src_path
            self._map[html_id] = target
            log.debug("[mkdocs_vwidalias] Registered id=%s -> %s", html_id, target)

        log.info("[mkdocs_vwidalias] Aliases to emit: %d", len(self._map))
        return nav

    def on_post_build(self, config: MkDocsConfig, **kwargs):
        if not self._map:
            log.info("[mkdocs_vwidalias] No IDs found; skipping alias generation.")
            return

        prefix = (self.config["alias_prefix"] or "").strip("/")
        emitted = 0

        for html_id, target in self._map.items():
            parts = [p for p in (prefix, html_id) if p]
            alias_dir = os.path.join(self._site_dir, *parts)
            Path(alias_dir).mkdir(parents=True, exist_ok=True)
            alias_index = os.path.join(alias_dir, "index.html")
            html = REDIRECT_TEMPLATE.format(target=target)
            write_file(html.encode("utf-8"), alias_index)
            emitted += 1
            log.debug("[mkdocs_vwidalias] Created alias: /%s -> /%s", "/".join(parts), target)

        log.info("[mkdocs_vwidalias] Emitted %d alias pages. Prefix='%s'", emitted, prefix)
