"""
Save business PDFs with unique, identifiable names:
  {CustomerName}_{DocumentNumber}_{YYYY-MM-DD}_{DocType}.pdf

Walk-in / anonymous sales use customer name "Walkin".
"""
from __future__ import annotations

import os
import re
from datetime import date, datetime
from typing import Optional, Tuple

from app.core.config import settings as app_settings

# Subfolder under app/static/documents/
DOC_FOLDERS = {
    "invoice": "invoices",
    "quotation": "quotations",
    "quote": "quotations",
    "receipt": "receipts",
    "statement": "statements",
    "customer_statement": "statements",
}


def normalize_customer_name_for_filename(name: Optional[str]) -> str:
    """Use the customer's real name; walk-in sales always filename as Walkin."""
    if not name or not str(name).strip():
        return "Walkin"
    s = str(name).strip()
    key = re.sub(r"[\s_\-]+", "", s.lower())
    if key in ("walkin", "walkincustomer", "walkincustomers", "anonymous"):
        return "Walkin"
    return s


def sanitize_filename_part(value: str, max_len: int = 60) -> str:
    if not value:
        return "Unknown"
    s = str(value).strip()
    s = re.sub(r'[<>:"/\\|?*\x00-\x1f]', "", s)
    s = re.sub(r"\s+", "_", s)
    s = re.sub(r"_+", "_", s).strip("._")
    if not s:
        return "Unknown"
    return s[:max_len]


def format_document_date(d: Optional[date | datetime | str]) -> str:
    if d is None:
        return datetime.now().strftime("%Y-%m-%d")
    if isinstance(d, datetime):
        return d.strftime("%Y-%m-%d")
    if isinstance(d, date):
        return d.isoformat()
    if isinstance(d, str):
        return d[:10] if len(d) >= 10 else datetime.now().strftime("%Y-%m-%d")
    return datetime.now().strftime("%Y-%m-%d")


def normalize_document_number(document_type: str, document_number: Optional[str]) -> str:
    """Ensure every PDF name includes a real document number (invoice / receipt / quote / statement)."""
    num = (document_number or "").strip()
    if num:
        return num

    type_prefix = {
        "invoice": "INV",
        "quotation": "QUO",
        "quote": "QUO",
        "receipt": "RCP",
        "statement": "STMT",
        "customer_statement": "STMT",
    }.get(document_type.lower(), "DOC")
    return f"{type_prefix}-{datetime.now().strftime('%Y%m%d-%H%M%S')}"


def build_document_filename(
    document_type: str,
    customer_name: str,
    created_date: Optional[date | datetime | str],
    document_number: str,
) -> str:
    """
    Customer name first (Walkin for walk-in sales), then document number for uniqueness.

    Example: Acme_Trading_INV-20260530-0001_2026-05-30_Invoice.pdf
    Example: Walkin_RCP-20260428-66CCDD91_2026-05-30_Receipt.pdf
    """
    type_label = {
        "invoice": "Invoice",
        "quotation": "Quotation",
        "quote": "Quotation",
        "receipt": "Receipt",
        "statement": "Statement",
        "customer_statement": "Statement",
    }.get(document_type.lower(), document_type.replace("_", " ").title())

    doc_num = sanitize_filename_part(
        normalize_document_number(document_type, document_number),
        max_len=80,
    )
    customer = sanitize_filename_part(normalize_customer_name_for_filename(customer_name))
    when = format_document_date(created_date)
    return f"{customer}_{doc_num}_{when}_{type_label}.pdf"


def documents_base_dir() -> str:
    base = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "static", "documents"))
    os.makedirs(base, exist_ok=True)
    return base


def save_document_pdf(
    document_type: str,
    pdf_bytes: bytes,
    customer_name: str,
    created_date: Optional[date | datetime | str],
    document_number: str,
) -> Tuple[str, str, str]:
    """
    Write PDF to static/documents/{type}/ and return (absolute_path, public_url_path, filename).
    public_url_path is like /static/documents/invoices/Name_date_Invoice_num.pdf
    """
    folder = DOC_FOLDERS.get(document_type.lower(), document_type.lower())
    target_dir = os.path.join(documents_base_dir(), folder)
    os.makedirs(target_dir, exist_ok=True)

    filename = build_document_filename(
        document_type, customer_name, created_date, document_number
    )
    filepath = os.path.join(target_dir, filename)

    # Avoid overwrite — append short suffix if exists
    if os.path.exists(filepath):
        base, ext = os.path.splitext(filename)
        for i in range(2, 100):
            alt = f"{base}_{i}{ext}"
            alt_path = os.path.join(target_dir, alt)
            if not os.path.exists(alt_path):
                filename = alt
                filepath = alt_path
                break

    with open(filepath, "wb") as f:
        f.write(pdf_bytes)

    public_path = f"/static/documents/{folder}/{filename}"
    return filepath, public_path, filename


def public_absolute_url(public_path: str) -> str:
    base = (app_settings.erp_public_url or "").rstrip("/")
    if not base:
        return public_path
    if not public_path.startswith("/"):
        public_path = "/" + public_path
    return f"{base}{public_path}"
