"""Bootstrap user passwords — run once after deploy or to reset everyone.

Generates a 6-char alphanumeric password for every user that doesn't have
one set, hashes it with bcrypt, writes the hash to DB, and prints the
plain-text passwords ONCE so the admin can hand them out.

Usage:
    python scripts/init_passwords.py              # only users without password
    python scripts/init_passwords.py --all        # reset EVERY user (force)
    python scripts/init_passwords.py --user lovro # reset specific user

After running, the plain-text passwords are NEVER recoverable — bcrypt is
one-way. Copy them out of the terminal immediately. Re-run with --user
to issue a new one if needed.
"""
from __future__ import annotations

import argparse
import secrets
import string
import sys
from pathlib import Path

# Make project root importable
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from sqlalchemy import text  # noqa: E402

from backend.services.auth_service import hash_password  # noqa: E402
from db.connection import get_engine  # noqa: E402


PASSWORD_LEN = 6
ALPHABET = string.ascii_lowercase + string.digits  # readable, no ambiguous chars


def gen_password(length: int = PASSWORD_LEN) -> str:
    """Cryptographically-random N-char password from a-z + 0-9.
    Excludes confusing chars (no 1/l/I, no 0/O)."""
    safe = "abcdefghjkmnpqrstuvwxyz23456789"  # removed: i l o 0 1
    return "".join(secrets.choice(safe) for _ in range(length))


def main():
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("--all", action="store_true",
                     help="Reset password for EVERY user (force)")
    ap.add_argument("--user", type=str,
                     help="Reset a specific username only")
    args = ap.parse_args()

    eng = get_engine()
    with eng.connect() as conn:
        # Build query based on args
        if args.user:
            rows = conn.execute(
                text("SELECT id, username, display_name FROM users "
                      "WHERE LOWER(username) = LOWER(:u)"),
                {"u": args.user},
            ).fetchall()
            if not rows:
                print(f"User not found: {args.user}")
                sys.exit(1)
        elif args.all:
            rows = conn.execute(
                text("SELECT id, username, display_name FROM users "
                      "ORDER BY id")
            ).fetchall()
        else:
            rows = conn.execute(
                text("SELECT id, username, display_name FROM users "
                      "WHERE password_hash IS NULL OR password_hash = '' "
                      "ORDER BY id")
            ).fetchall()
            if not rows:
                print("All users already have a password set. "
                       "Use --all to reset everyone, or --user X to reset one.")
                sys.exit(0)

        print(f"Generating passwords for {len(rows)} user(s)…")
        print()
        print("=" * 60)
        print(f"{'ID':>3}  {'USERNAME':<14} {'DISPLAY':<14} {'PASSWORD':<10}")
        print("=" * 60)

        for uid, uname, display in rows:
            pw = gen_password()
            hashed = hash_password(pw)
            conn.execute(
                text("UPDATE users SET password_hash = :h WHERE id = :uid"),
                {"h": hashed, "uid": uid},
            )
            print(f"{uid:>3}  {uname:<14} {(display or ''):<14} {pw:<10}")
        conn.commit()

        print("=" * 60)
        print()
        print("⚠ COPY THESE NOW. Passwords are bcrypt-hashed in DB and cannot")
        print("  be recovered. Re-run with --user <name> to issue a new one.")
        print()
        print("Hand each user their password through a secure channel.")
        print("Users can change their own via /api/auth/change-password.")


if __name__ == "__main__":
    main()
