from __future__ import annotations

import hashlib
import json
import secrets
from pathlib import Path

from app.core.config import SERVER_DIR

ADMIN_SECRET_FILE = SERVER_DIR / ".secrets" / "admin.json"


def read_admin_secret() -> dict[str, object] | None:
    if not ADMIN_SECRET_FILE.exists():
        return None

    try:
        payload = json.loads(ADMIN_SECRET_FILE.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return None

    if (
        payload
        and payload.get("algorithm") == "scrypt"
        and isinstance(payload.get("username"), str)
        and isinstance(payload.get("salt"), str)
        and isinstance(payload.get("derived_key"), str)
    ):
        return payload

    return None


def verify_admin_secret(password: str, record: dict[str, object]) -> bool:
    try:
        salt = bytes.fromhex(str(record["salt"]))
        stored_key = bytes.fromhex(str(record["derived_key"]))
        key_length = int(record.get("key_length", 64))
        n_value = int(record.get("N", 16384))
        r_value = int(record.get("r", 8))
        p_value = int(record.get("p", 1))
    except (KeyError, TypeError, ValueError):
        return False

    derived_key = hashlib.scrypt(
        password.encode("utf-8"),
        salt=salt,
        n=n_value,
        r=r_value,
        p=p_value,
        dklen=key_length,
    )
    return secrets.compare_digest(derived_key, stored_key)


def legacy_admin_secret_to_password_hash(record: dict[str, object]) -> str:
    salt = str(record["salt"])
    derived_key = str(record["derived_key"])
    key_length = int(record.get("key_length", 64))
    n_value = int(record.get("N", 16384))
    r_value = int(record.get("r", 8))
    p_value = int(record.get("p", 1))
    return f"scrypt${n_value}${r_value}${p_value}${key_length}${salt}${derived_key}"
