"""Turn an uploaded filename into a title a person would have typed.

Staff upload files named things like `Strata-Corp-25-2025-AGM-Minutes_v2 (1).pdf`.
Making them retype a title for every file is exactly the friction that keeps
people emailing documents instead, so the uploader proposes one and lets them
correct it.
"""
import os
import re

# Noise that shows up in filenames but never belongs in a title.
NOISE = re.compile(
    r"\b(final|draft|v\d+|version\s*\d+|copy|new|updated?|scan(ned)?|"
    r"signed|compressed|revised)\b",
    re.I,
)
DUP_SUFFIX = re.compile(r"[\s_-]*\(\d+\)\s*$")          # "... (1)"
LEADING_DATE = re.compile(r"^\s*(\d{4}[-_]\d{2}[-_]\d{2}|\d{8})[\s_-]+")
SEPARATORS = re.compile(r"[_\-\.\s]+")

# Words that should keep their conventional casing.
UPPER = {"agm", "pdf", "d&o", "hoa", "id", "ii", "iii", "iv", "bcqs", "capex", "q1",
         "q2", "q3", "q4", "us", "uk", "tci"}
LOWER = {"a", "an", "and", "as", "at", "by", "for", "from", "in", "of", "on",
         "or", "the", "to", "with"}


def title_from_filename(filename):
    """A readable title, or "" if nothing usable survives."""
    stem = os.path.splitext(os.path.basename(filename or ""))[0]
    stem = DUP_SUFFIX.sub("", stem)
    stem = LEADING_DATE.sub("", stem)
    stem = SEPARATORS.sub(" ", stem)
    stem = NOISE.sub("", stem)
    stem = re.sub(r"\s{2,}", " ", stem).strip(" -_")

    if len(stem) < 3 or not re.search(r"[A-Za-z]{2}", stem):
        return ""
    return _titlecase(stem)[:255]


def _titlecase(text):
    words = text.split()
    out = []
    for index, word in enumerate(words):
        bare = word.strip("()[],.").lower()
        if bare in UPPER:
            out.append(word.upper())
        elif bare in LOWER and index != 0:
            out.append(word.lower())
        elif word.isupper() and len(word) > 3:
            # Shouty filenames read badly as titles.
            out.append(word.capitalize())
        elif word[:1].islower():
            out.append(word[:1].upper() + word[1:])
        else:
            out.append(word)
    return " ".join(out)


def title_from_pdf(uploaded_file):
    """A PDF's embedded title, when it is better than nothing.

    Producers leave junk in this field ("Microsoft Word - Doc1"), so anything
    that looks generated is rejected and the filename wins instead.
    """
    try:
        from pypdf import PdfReader
    except ImportError:
        return ""
    try:
        uploaded_file.seek(0)
        meta = PdfReader(uploaded_file).metadata or {}
        candidate = (meta.get("/Title") or "").strip()
    except Exception:
        return ""
    finally:
        try:
            uploaded_file.seek(0)
        except Exception:
            pass

    if not candidate or len(candidate) < 4 or len(candidate) > 200:
        return ""
    junk = ("microsoft word", "untitled", "document1", ".doc", ".pdf",
            "print", "adobe", "pdfcreator")
    if any(word in candidate.lower() for word in junk):
        return ""
    return candidate[:255]


def suggest_title(uploaded_file):
    """Best available title for an upload: PDF metadata if sane, else filename."""
    name = getattr(uploaded_file, "name", "") or ""
    if name.lower().endswith(".pdf"):
        from_pdf = title_from_pdf(uploaded_file)
        if from_pdf:
            return from_pdf
    return title_from_filename(name) or os.path.splitext(os.path.basename(name))[0][:255]
