"""Attachment storage: validated uploads, safe paths (no traversal), hashing, malware-scan hook."""
import hashlib
import os
import re
import secrets

from app.core.config import settings

BASE_DIR = settings.UPLOAD_DIR
if not os.path.isabs(BASE_DIR):
    BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), BASE_DIR)

MIME_BY_EXT = {
    "pdf": "application/pdf", "html": "text/html", "htm": "text/html", "txt": "text/plain",
    "png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg",
}


def allowed_ext(filename: str, allowed: str = None) -> bool:
    ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
    allowed = (allowed or settings.ALLOWED_ATTACHMENT_EXTS).split(",")
    return ext in [a.strip().lower() for a in allowed]


def safe_join(rel_path: str) -> str:
    """Resolve a stored relative path under UPLOAD_DIR; refuse traversal."""
    root = os.path.realpath(BASE_DIR)
    candidate = os.path.realpath(os.path.join(root, rel_path))
    if not candidate.startswith(root + os.sep) and candidate != root:
        raise ValueError("Path traversal detected")
    return candidate


def save_upload(filename: str, content: bytes) -> dict:
    """Store an uploaded attachment with a random name component. Returns metadata."""
    os.makedirs(BASE_DIR, exist_ok=True)
    ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else "bin"
    safe_name = re.sub(r"[^A-Za-z0-9._-]", "_", filename)[:120]
    stored = f"{secrets.token_hex(8)}_{safe_name}"
    path = os.path.join(BASE_DIR, "attachments", stored)
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "wb") as f:
        f.write(content)
    sha = hashlib.sha256(content).hexdigest()
    return {"stored_path": os.path.join("attachments", stored), "filename": filename,
            "size": len(content), "sha256": sha,
            "mime_type": MIME_BY_EXT.get(ext, "application/octet-stream")}


def read_attachment_bytes(att) -> bytes | None:
    try:
        with open(safe_join(att.stored_path), "rb") as f:
            return f.read()
    except Exception:
        return None


def delete_attachment_file(att) -> None:
    try:
        os.remove(safe_join(att.stored_path))
    except Exception:
        pass


def scan_for_malware(content: bytes, filename: str) -> tuple:
    """Integration point for AV scanning (e.g. ClamAV). Returns (clean, message).

    Wire a real scanner here in production (clamd, VirusTotal API, etc.).
    Heuristic baseline: reject embedded PE/ELF executables regardless of extension.
    """
    if content[:2] == b"MZ" or content[:4] == b"\x7fELF":
        return False, "Executable file signature detected"
    return True, "no scanner configured; heuristic pass"
