import os
import uuid
import re
import bleach
from fastapi import UploadFile
from config import settings

ALLOWED_TAGS = [
    "p", "br", "strong", "em", "u", "s", "a", "img", "ul", "ol", "li",
    "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "code",
    "table", "thead", "tbody", "tr", "th", "td", "div", "span",
    "iframe", "figure", "figcaption", "video", "audio", "source", "hr",
]
ALLOWED_ATTRS = {
    "*": ["class", "style", "dir", "id"],
    "a": ["href", "target", "rel"],
    "img": ["src", "alt", "width", "height", "loading"],
    "iframe": ["src", "width", "height", "frameborder", "allowfullscreen", "allow"],
    "video": ["src", "controls", "width", "height", "preload", "poster"],
    "audio": ["src", "controls", "preload"],
    "source": ["src", "type"],
    "td": ["colspan", "rowspan"],
    "th": ["colspan", "rowspan"],
}


def sanitize_html(html: str) -> str:
    if not html:
        return ""
    return bleach.clean(
        html, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRS,
        strip=True, protocols=["http", "https", "mailto"],
    )


def slugify(text: str) -> str:
    text = re.sub(r"[^\w\s-]", "", text.lower().strip())
    text = re.sub(r"[\s_]+", "-", text)
    text = re.sub(r"-+", "-", text).strip("-")
    return text or uuid.uuid4().hex[:8]


async def save_upload(file: UploadFile, subfolder: str, allowed_ext: set) -> str:
    if not file or not file.filename:
        return ""
    ext = file.filename.rsplit(".", 1)[-1].lower() if "." in file.filename else ""
    if ext not in allowed_ext:
        return ""
    filename = f"{uuid.uuid4().hex}.{ext}"
    dest = os.path.join(settings.UPLOAD_DIR, subfolder, filename)
    content = await file.read()
    if len(content) > settings.MAX_UPLOAD_MB * 1024 * 1024:
        return ""
    with open(dest, "wb") as f:
        f.write(content)
    return f"/static/uploads/{subfolder}/{filename}"


def delete_file(path: str):
    if not path:
        return
    full = os.path.join(os.path.dirname(__file__), path.lstrip("/"))
    if os.path.isfile(full):
        os.remove(full)


def get_setting(db, key: str, default: str = "") -> str:
    from models import SiteSettings
    s = db.query(SiteSettings).filter_by(key=key).first()
    return s.value if s else default


def set_setting(db, key: str, value: str):
    from models import SiteSettings
    s = db.query(SiteSettings).filter_by(key=key).first()
    if s:
        s.value = value
    else:
        db.add(SiteSettings(key=key, value=value))
    db.commit()
