"""Shared utilities for the Lock Pipeline scripts."""
from __future__ import annotations

from datetime import datetime
import os
import unicodedata

_ABJAD_VALUES = {
    "\u0627": 1,
    "\u0628": 2,
    "\u062c": 3,
    "\u062f": 4,
    "\u0647": 5,
    "\u0648": 6,
    "\u0632": 7,
    "\u062d": 8,
    "\u0637": 9,
    "\u064a": 10,
    "\u0643": 20,
    "\u0644": 30,
    "\u0645": 40,
    "\u0646": 50,
    "\u0633": 60,
    "\u0639": 70,
    "\u0641": 80,
    "\u0635": 90,
    "\u0642": 100,
    "\u0631": 200,
    "\u0634": 300,
    "\u062a": 400,
    "\u062b": 500,
    "\u062e": 600,
    "\u0630": 700,
    "\u0636": 800,
    "\u0638": 900,
    "\u063a": 1000,
}

_ABJAD_NORMALIZE = {
    "\u0623": "\u0627",  # alef with hamza above
    "\u0625": "\u0627",  # alef with hamza below
    "\u0622": "\u0627",  # alef madda
    "\u0671": "\u0627",  # alef wasla
    "\u0649": "\u064a",  # alef maqsura -> ya
    "\u0626": "\u064a",  # ya with hamza -> ya
    "\u0624": "\u0648",  # waw with hamza -> waw
    "\u0629": "\u0647",  # ta marbuta -> ha
    "\u0621": "\u0627",  # standalone hamza -> alef
}

_ABJAD_IGNORE = {
    "\u0640",  # tatweel
    "\u200c",  # zwnj
    "\u200d",  # zwj
    "\ufeff",  # bom
}


def _iter_abjad_letters(text: str):
    normalized = unicodedata.normalize("NFKC", text)
    for ch in normalized:
        if ch in _ABJAD_IGNORE:
            continue

        # Skip Arabic harakat, Quranic marks, and other combining symbols.
        if unicodedata.category(ch).startswith("M"):
            continue

        ch = _ABJAD_NORMALIZE.get(ch, ch)
        if ch in _ABJAD_VALUES:
            yield ch


def m4_m6_abjad_digits(text_value: object) -> tuple[str, str]:
    """Return corrected M4/M6 digit strings from verse text.

    M4 is forward abjad-letter concatenation.
    M6 is the exact reverse-letter mirror of M4.
    """
    text = "" if text_value is None else str(text_value)
    letters = list(_iter_abjad_letters(text))
    if not letters:
        return "0", "0"

    m4 = "".join(str(_ABJAD_VALUES[ch]) for ch in letters)
    m6 = "".join(str(_ABJAD_VALUES[ch]) for ch in reversed(letters))
    return m4, m6


def _generated_timestamp() -> str:
    """Return a timestamp string for output headers.

    Override order (highest priority first):
    1. LOCK_PIPELINE_GENERATED_AT  – use this exact string verbatim.
    2. LOCK_PIPELINE_DETERMINISTIC – any truthy value → fixed epoch string
       (enables bit-exact comparison across runs).
    3. Default                     – current wall-clock time.
    """
    fixed = os.getenv("LOCK_PIPELINE_GENERATED_AT")
    if fixed:
        return fixed

    deterministic = os.getenv("LOCK_PIPELINE_DETERMINISTIC", "").lower()
    if deterministic in {"1", "true", "yes", "on"}:
        return "1970-01-01 00:00:00"

    return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
