# 경로/파일: realcom-nas-ui/tools/webdav_gen.py
# 목적: shares 기반 WebDAV Nginx conf 자동 생성 + 안전 검증 + reload

import os
import re
import subprocess

from share import list_share

NGINX_CONF_PATH = "/etc/nginx/sites-available/webdav-shares.conf"
NGINX_LINK_PATH = "/etc/nginx/sites-enabled/webdav-shares.conf"
NGINX_PORT = 8000

# ✅ 보안 옵션 (필요하면 켜)
ENABLE_BASIC_AUTH = True
BASIC_AUTH_REALM = "RealNAS WebDAV"
BASIC_AUTH_FILE = "/etc/nginx/.htpasswd"   # 네 시스템에서 이미 쓰는 파일로 맞춰라

# ✅ IP 제한(내부망이면 추천)
ENABLE_IP_ALLOWLIST = False
ALLOW_CIDRS = None   # or []


# ✅ share name 허용 규칙 (nginx location 안전)
SAFE_NAME_RE = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")

def _is_safe_share_name(name: str) -> bool:
    return bool(name and SAFE_NAME_RE.match(name))

def _realpath(p: str) -> str:
    try:
        return os.path.realpath(p)
    except Exception:
        return ""

def make_webdav_location_block(share: dict) -> str:
    share_name = (share.get("name") or "").strip()
    share_path = (share.get("path") or "").strip()

    if not _is_safe_share_name(share_name):
        return ""

    rp = _realpath(share_path)
    if not rp or not os.path.isdir(rp):
        return ""

    # ✅ nginx alias는 trailing slash 규칙 맞춤
    # location /name/  + alias /real/path/  (OK)
    auth_lines = ""
    if ENABLE_BASIC_AUTH:
        auth_lines += f'\n        auth_basic "{BASIC_AUTH_REALM}";\n'
        auth_lines += f"        auth_basic_user_file {BASIC_AUTH_FILE};\n"

    ip_lines = ""
    if ENABLE_IP_ALLOWLIST and ALLOW_CIDRS:
        for cidr in ALLOW_CIDRS:
            ip_lines += f"        allow {cidr};\n"
        ip_lines += "        deny all;\n"

    return f"""
    location /{share_name}/ {{
        alias {rp}/;

        {auth_lines}{ip_lines}

        # WebDAV
        dav_methods     PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS;
        dav_access      user:rw group:rw all:;

        client_max_body_size 2G;
        create_full_put_path on;

        autoindex on;
        charset utf-8;
    }}
    """

def generate_nginx_conf(shares: list[dict]) -> str:
    blocks = []
    for s in shares:
        b = make_webdav_location_block(s)
        if b.strip():
            blocks.append(b)

    return f"""server {{
    listen {NGINX_PORT};
    server_name _;

    # Auto-generated WebDAV shares
{''.join(blocks)}
}}
"""

def _ensure_symlink(target: str, link_path: str) -> None:
    # link_path가 존재하면:
    # - 심링크인데 target이 다르면 교체
    # - 일반 파일이면 백업 후 교체
    if os.path.islink(link_path):
        cur = os.readlink(link_path)
        if cur != target:
            os.unlink(link_path)
            os.symlink(target, link_path)
        return

    if os.path.exists(link_path):
        bak = link_path + ".bak"
        try:
            os.rename(link_path, bak)
        except Exception:
            pass

    os.symlink(target, link_path)

def save_and_reload_nginx(conf_text: str) -> None:
    with open(NGINX_CONF_PATH, "w", encoding="utf-8") as f:
        f.write(conf_text)

    _ensure_symlink(NGINX_CONF_PATH, NGINX_LINK_PATH)

    subprocess.run(["sudo", "nginx", "-t"], check=True)
    subprocess.run(["sudo", "systemctl", "reload", "nginx"], check=True)
    print("[OK] Nginx WebDAV conf updated & reloaded")

def main():
    shares = list_share() or []
    print(f"[INFO] loaded shares: {len(shares)}")

    conf_text = generate_nginx_conf(shares)
    print("[INFO] preview:\n")
    print(conf_text)

    save_and_reload_nginx(conf_text)

if __name__ == "__main__":
    main()
