"""fiche_utils.py – outils de lecture / rendu des fiches Markdown (indices et opérations)

Dépendances :
  pip install python-frontmatter pyyaml jinja2

Usage :
    from fiche_utils import load_seuils, render_fiche_markdown

    seuils = load_seuils("config/indices_seuils.yaml")
    markdown_rendered = render_fiche_markdown(raw_md_text, seuils)
"""

from __future__ import annotations

import os
import pathlib
import re
from datetime import datetime, timezone

import frontmatter
import jinja2
import yaml

from utils.gitea import recuperer_date_dernier_commit


def load_seuils(path: str | pathlib.Path = "config/indices_seuils.yaml") -> dict:
    """Charge le fichier YAML des seuils et renvoie le dict 'seuils'.

    Args:
        path (str | pathlib.Path, optional): Chemin vers le fichier des seuils. Defaults to "config/indices_seuils.yaml".

    Returns:
        Dict: Dictionnaire contenant les seuils.
    """
    data = yaml.safe_load(pathlib.Path(path).read_text(encoding="utf-8"))
    return data.get("seuils", {})

def _migrate_metadata(meta: dict) -> dict:
    """Normalise les clés YAML (ex : sheet_type → type_fiche).

    Args:
        meta (Dict): Métadonnées à normaliser.

    Returns:
        Dict: Métadonnées normalisées.
    """
    keymap = {
        "sheet_type": "type_fiche",
        "indice_code": "indice_court",  # si besoin
    }
    for old, new in keymap.items():
        if old in meta and new not in meta:
            meta[new] = meta.pop(old)
    return meta

def render_fiche_markdown(
    md_text: str,
    seuils: dict,
    license_path: str = "assets/licence.md"
) -> str:
    """Renvoie la fiche rendue (Markdown) avec les placeholders remplacés et le tableau de version.

    Args:
        md_text (str): Contenu Markdown brut.
        seuils (Dict): Tableau des versions.
        license_path (str, optional): Chemin vers le fichier de licence. Defaults to "assets/licence.md".

    Returns:
        str: Fiche Markdown rendue avec les placeholders remplacés et la table de version.

    Note:
        - Les licences sont ajoutées après le tableau de version.
        - Les titres de niveau 2 doivent être présents pour l'insertion automatique de licence.
    """
    post = frontmatter.loads(md_text)
    meta = _migrate_metadata(dict(post.metadata))
    body_template = post.content

    # Instancie Jinja2 en 'StrictUndefined' pour signaler les placeholders manquants.
    env = jinja2.Environment(
        undefined=jinja2.StrictUndefined,
        autoescape=False,
        trim_blocks=True,
        lstrip_blocks=True,
    )
    tpl = env.from_string(body_template)
    rendered_body = tpl.render(**meta, seuils=seuils)

    # Option : ajoute automatiquement titre + tableau version si absent.
    header = f"# {meta.get('indice', meta.get('titre',''))} ({meta.get('indice_court','')})"
    if not re.search(r"^# ", rendered_body, flags=re.M):
        rendered_body = f"""{header}

{rendered_body}"""

    # Charger le contenu de la licence
    try:
        license_content = pathlib.Path(license_path).read_text(encoding="utf-8")

        # Insérer la licence après le tableau de version et avant le premier titre h2
        # Trouver la position du premier titre h2
        h2_match = re.search(r"^## ", rendered_body, flags=re.M)

        if h2_match:
            h2_position = h2_match.start()
            rendered_body = f"{rendered_body[:h2_position]}\n\n{license_content}\n\n{rendered_body[h2_position:]}"
        else:
            # S'il n'y a pas de titre h2, ajouter la licence à la fin
            rendered_body = f"{rendered_body}\n\n{license_content}"
    except Exception as e:
        # En cas d'erreur lors de la lecture du fichier de licence, continuer sans l'ajouter
        import streamlit as st
        st.error(e)

    return rendered_body


def fichier_plus_recent(
    chemin_fichier: str|None,
    reference: datetime
) -> bool:
    """Vérifie si un fichier est plus récent que la référence donnée.

    Args:
        chemin_fichier (str): Chemin vers le fichier à vérifier.
        reference (datetime): Référence temporelle de comparaison.

    Returns:
        bool: True si le fichier est plus récent, False sinon.
    """
    try:
        modif = datetime.fromtimestamp(os.path.getmtime(chemin_fichier), tz=timezone.utc)
        return modif > reference
    except Exception:
        return False

def doit_regenerer_fiche(
    html_path: str,
    fiche_type: str,
    fiche_choisie: str,
    commit_url: str,
    fichiers_criticite: dict[str, str]
) -> bool:
    """Détermine si une fiche doit être regénérée.

    Args:
        html_path (str): Chemin vers le fichier HTML.
        fiche_type (str): Type de la fiche.
        fiche_choisie (str): Nom choisi pour la fiche.
        commit_url (str): URL du dernier commit.
        fichiers_criticite (Dict[str, str]): Dictionnaire des fichiers critiques.

    Returns:
        bool: True si la fiche doit être regénérée, False sinon.
    """
    if not os.path.exists(html_path):
        return True

    local_mtime = datetime.fromtimestamp(os.path.getmtime(html_path), tz=timezone.utc)
    remote_mtime = recuperer_date_dernier_commit(commit_url)

    if remote_mtime is None or remote_mtime > local_mtime:
        return True

    if fichier_plus_recent(fichiers_criticite.get("IHH"), local_mtime):
        return True

    if fiche_type == "minerai" or "minerai" in fiche_choisie.lower():
        if fichier_plus_recent(fichiers_criticite.get("IVC"), local_mtime):
            return True
        if fichier_plus_recent(fichiers_criticite.get("ICS"), local_mtime):
            return True

    return False
