"""촬영 결과를 세션 폴더에 저장하고 오래된 것을 지웁니다."""
import re
import secrets
import shutil
import time
from pathlib import Path

from .config import DATA_DIR, MAX_UPLOAD_MB, RETENTION_HOURS

ID_RE = re.compile(r"^[a-f0-9]{8}$")
PHOTO_NAME = "photo.png"
VIDEO_EXT = {"video/mp4": "mp4", "video/webm": "webm"}


def new_id() -> str:
    return secrets.token_hex(4)


def valid_id(sid: str) -> bool:
    return bool(ID_RE.match(sid or ""))


def session_dir(sid: str) -> Path:
    return DATA_DIR / sid


async def save_upload(sid: str, upload, filename: str) -> int:
    """업로드를 세션 폴더에 저장하고 바이트 수를 돌려줍니다."""
    d = session_dir(sid)
    d.mkdir(parents=True, exist_ok=True)
    limit = MAX_UPLOAD_MB * 1024 * 1024
    written = 0
    with open(d / filename, "wb") as f:
        while True:
            chunk = await upload.read(1024 * 512)
            if not chunk:
                break
            written += len(chunk)
            if written > limit:
                f.close()
                shutil.rmtree(d, ignore_errors=True)
                raise ValueError("파일이 너무 큽니다")
            f.write(chunk)
    return written


def video_name(content_type: str, filename: str) -> str:
    ext = VIDEO_EXT.get((content_type or "").split(";")[0].strip())
    if not ext:
        ext = "mp4" if str(filename).lower().endswith(".mp4") else "webm"
    return "video." + ext


def list_files(sid: str):
    d = session_dir(sid)
    if not d.is_dir():
        return []
    out = []
    for p in sorted(d.iterdir()):
        if not p.is_file():
            continue
        out.append(
            {
                "name": p.name,
                "kind": "photo" if p.name == PHOTO_NAME else "video",
                "size": p.stat().st_size,
                "url": "/files/{}/{}".format(sid, p.name),
            }
        )
    return out


def purge_old() -> int:
    """보관 시간이 지난 세션 폴더를 정리합니다."""
    if not DATA_DIR.is_dir():
        return 0
    cutoff = time.time() - RETENTION_HOURS * 3600
    removed = 0
    for d in DATA_DIR.iterdir():
        if d.is_dir() and d.stat().st_mtime < cutoff:
            shutil.rmtree(d, ignore_errors=True)
            removed += 1
    return removed
