# 경로/파일: realcom-nas-ui/modules/nginx_user.py
# 붙여넣기: 이 파일 전체 교체

# © Realcom. All rights reserved.
# Unauthorized copying, modification, or redistribution is prohibited.

from __future__ import annotations

import os
import re
import subprocess
from typing import List, Tuple

HTPASSWD_FILE = "/etc/nginx/.htpasswd"
HTPASSWD_BIN = "/usr/bin/htpasswd"

# 아이디 제한(nginx basic auth 안전하게)
_USERNAME_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$")


def _sudo_run(cmd: List[str]) -> subprocess.CompletedProcess:
    """
    sudo -n: 비번 요구하면 즉시 실패 (웹에서 멈춤 방지)
    capture_output/text: 에러를 화면에 띄울 수 있게
    """
    return subprocess.run(
        ["sudo", "-n", *cmd],
        capture_output=True,
        text=True
    )


def _ensure_parent_dir() -> None:
    parent = os.path.dirname(HTPASSWD_FILE) or "/"
    os.makedirs(parent, exist_ok=True)


def _normalize_user(username: str) -> str:
    return (username or "").strip()


def _validate_username(username: str) -> Tuple[bool, str]:
    if not username:
        return False, "사용자명은 필수입니다."
    if not _USERNAME_RE.match(username):
        return False, "아이디 형식 오류(영문/숫자/._- 만 가능, 1~36자)."
    return True, ""


def _format_err(r: subprocess.CompletedProcess) -> str:
    msg = (r.stderr or "").strip() or (r.stdout or "").strip()
    return msg if msg else f"returncode={r.returncode}"


def list_nginx_users() -> List[str]:
    """
    htpasswd 파일에 등록된 사용자 목록 반환
    """
    users: List[str] = []
    if not os.path.exists(HTPASSWD_FILE):
        return users

    try:
        with open(HTPASSWD_FILE, "r", encoding="utf-8", errors="ignore") as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                if ":" not in line:
                    continue
                user = line.split(":", 1)[0].strip()
                if user:
                    users.append(user)
    except Exception:
        return []

    # 중복 제거 + 정렬
    return sorted(set(users))


def add_nginx_user(username: str, password: str) -> Tuple[bool, str]:
    """
    새로운 사용자 추가 (중복 아이디 불가)
    - 파일 없으면 -c로 생성
    - sudo -n htpasswd 사용 (권한 문제 해결)
    """
    username = _normalize_user(username)
    password = password or ""

    ok, msg = _validate_username(username)
    if not ok:
        return False, msg
    if not password:
        return False, "비밀번호는 필수입니다."

    if username in list_nginx_users():
        return False, "이미 존재하는 사용자명입니다."

    _ensure_parent_dir()

    if not os.path.exists(HTPASSWD_FILE):
        r = _sudo_run([HTPASSWD_BIN, "-bBc", HTPASSWD_FILE, username, password])
    else:
        r = _sudo_run([HTPASSWD_BIN, "-bB", HTPASSWD_FILE, username, password])

    if r.returncode != 0:
        return False, f"사용자 추가 실패: {_format_err(r)}"

    return True, f"사용자 '{username}'가 추가되었습니다."


def remove_nginx_user(username: str) -> Tuple[bool, str]:
    """
    사용자 삭제
    - htpasswd -D 사용
    """
    username = _normalize_user(username)

    ok, msg = _validate_username(username)
    if not ok:
        return False, msg

    if username not in list_nginx_users():
        return False, "존재하지 않는 사용자입니다."

    r = _sudo_run([HTPASSWD_BIN, "-D", HTPASSWD_FILE, username])
    if r.returncode != 0:
        return False, f"사용자 삭제 실패: {_format_err(r)}"

    return True, f"사용자 '{username}'가 삭제되었습니다."


def change_nginx_user_password(username: str, password: str) -> Tuple[bool, str]:
    """
    사용자 비밀번호 변경
    """
    username = _normalize_user(username)
    password = password or ""

    ok, msg = _validate_username(username)
    if not ok:
        return False, msg
    if not password:
        return False, "비밀번호는 필수입니다."

    if username not in list_nginx_users():
        return False, "존재하지 않는 사용자입니다."

    r = _sudo_run([HTPASSWD_BIN, "-bB", HTPASSWD_FILE, username, password])
    if r.returncode != 0:
        return False, f"비밀번호 변경 실패: {_format_err(r)}"

    return True, f"사용자 '{username}' 비밀번호가 변경되었습니다."
