import hashlib
import hmac
import re
import secrets
from werkzeug.security import check_password_hash, generate_password_hash

_EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
_USERNAME_STARTS_WITH_LETTER = re.compile(r"^[A-Za-z]")


def hash_password(password: str) -> str:
    return generate_password_hash(password, method="scrypt")


def verify_password(stored_password: str, provided_password: str) -> bool:
    if not stored_password:
        return False
    if stored_password.startswith(("pbkdf2:", "scrypt:")):
        return check_password_hash(stored_password, provided_password)
    return hmac.compare_digest(stored_password, provided_password)


def needs_password_rehash(stored_password: str) -> bool:
    return bool(stored_password) and not stored_password.startswith(("pbkdf2:", "scrypt:"))


def generate_otp(length: int = 6) -> str:
    return "".join(secrets.choice("0123456789") for _ in range(length))


def hash_otp(code: str) -> str:
    return hashlib.sha256(code.encode("utf-8")).hexdigest()


def verify_otp(code: str, code_hash: str) -> bool:
    if not code or not code_hash:
        return False
    return hmac.compare_digest(hash_otp(code.strip()), code_hash)


def normalize_email(email: str) -> str:
    return (email or "").strip().lower()


def is_valid_email(email: str) -> bool:
    return bool(_EMAIL_RE.match(normalize_email(email)))


def username_starts_with_letter(username: str) -> bool:
    """True if username starts with an ASCII letter (A–Z or a–z)."""
    return bool(username and _USERNAME_STARTS_WITH_LETTER.match(username))


def normalize_phone(phone: str) -> str:
    digits = re.sub(r"\D", "", phone or "")
    if not digits:
        return ""
    if digits.startswith("92") and len(digits) >= 12:
        return f"+{digits}"
    if digits.startswith("0") and len(digits) >= 10:
        return f"+92{digits[1:]}"
    if len(digits) == 10 and digits.startswith("3"):
        return f"+92{digits}"
    if phone.strip().startswith("+"):
        return f"+{digits}"
    return f"+{digits}" if digits else ""


def is_valid_phone(phone: str) -> bool:
    normalized = normalize_phone(phone)
    return len(re.sub(r"\D", "", normalized)) >= 10
