# Copyright (C) 2026 Wilhelmus Dingenus de Pooter
# SPDX-License-Identifier: GPL-3.0-or-later
"""Filename convention for exports and recipes (pure, GUI-independent).

Convention: ``yyyymmdd_user_process_source`` where the source token is clipped
to 10 characters and every component is reduced to characters legal on all
common filesystems (Windows, macOS, Linux). Kept here, free of any Qt/QGIS
import, so it is unit-testable headlessly; the UI layer supplies the date and
the QGIS user name.
"""

import os
import re

# Characters illegal on Windows (the strictest common target) plus control
# bytes; the union covers macOS/Linux too.
_ILLEGAL = re.compile(r'[<>:"/\\|?*\x00-\x1f]')


def fs_safe(text):
    """Reduce a string to a filesystem-safe token: take the last path-ish
    component (so ``DOMAIN\\user`` -> ``user``), drop illegal characters, turn
    whitespace into hyphens, and trim leading/trailing dots, spaces, and
    separators (Windows rejects trailing dots/spaces)."""
    if not text:
        return ""
    s = re.split(r"[\\/]", str(text))[-1]
    s = _ILLEGAL.sub("", s)
    s = re.sub(r"\s+", "-", s)
    s = s.strip(". -_")
    return s


def source_stem(source_path):
    """The source folder/zip reduced to a safe stem (no extension)."""
    base = os.path.basename((source_path or "").rstrip("/\\"))
    base = os.path.splitext(base)[0]               # drop .zip / .000 etc.
    return fs_safe(base)


def build_filename(date, user, process, source, clip=10):
    """Assemble ``yyyymmdd_user_process_source`` with each part sanitised and
    the source clipped to ``clip`` characters. Empty parts get safe defaults."""
    user = fs_safe(user) or "user"
    process = fs_safe(process) or "doc"
    src = fs_safe(source)[:clip] or "source"
    return f"{date}_{user}_{process}_{src}"
