#!/opt/homebrew/bin/python3.11
"""
Sync users from SFTPGo to Momentry users table.

Usage:
    python3 scripts/sync_users_from_sftpgo.py
    python3 scripts/sync_users_from_sftpgo.py --sftpgo-url http://localhost:8080
    python3 scripts/sync_users_from_sftpgo.py --db "dbname=momentry user=accusys"

Environment:
    SFTPGO_BASE_URL   Default: http://localhost:8080
    DATABASE_URL      Default: dbname=momentry user=accusys host=localhost

This script does NOT copy passwords. It creates user records with placeholder
password hashes. The real password will be captured on the user's first
login through Momentry (which verifies against SFTPGo and caches the hash).
"""
import argparse
import json
import os
import sys
from typing import Any

import psycopg2
import psycopg2.extras
import requests


def get_sftpgo_users(sftpgo_url: str, admin_user: str, admin_pass: str) -> list[dict[str, Any]]:
    """Get all users from SFTPGo."""
    # Get admin token (SFTPGo uses GET, not POST)
    token_url = f"{sftpgo_url}/api/v2/token"
    resp = requests.get(token_url, auth=(admin_user, admin_pass), timeout=10)
    resp.raise_for_status()
    token = resp.json().get("access_token")
    if not token:
        print("ERROR: Failed to get SFTPGo admin token", file=sys.stderr)
        sys.exit(1)

    # List users
    users_url = f"{sftpgo_url}/api/v2/users"
    headers = {"Authorization": f"Bearer {token}"}
    resp = requests.get(users_url, headers=headers, timeout=10)
    resp.raise_for_status()
    return resp.json()


def main():
    parser = argparse.ArgumentParser(description="Sync SFTPGo users to Momentry")
    parser.add_argument("--sftpgo-url", default=os.getenv("SFTPGO_BASE_URL", "http://localhost:8080"))
    parser.add_argument("--db", default=os.getenv("DATABASE_URL", "dbname=momentry user=accusys host=localhost"))
    parser.add_argument("--admin-user", default="admin")
    parser.add_argument("--admin-pass", default=os.getenv("SFTPGO_ADMIN_PASSWORD", "Test3200Test3200"))
    parser.add_argument("--dry-run", action="store_true", help="Print what would be done without executing")
    args = parser.parse_args()

    # Fetch users from SFTPGo
    print(f"[SFTPGo] Connecting to {args.sftpgo_url}...")
    try:
        sftpgo_users = get_sftpgo_users(args.sftpgo_url, args.admin_user, args.admin_pass)
    except Exception as e:
        print(f"ERROR: Failed to fetch SFTPGo users: {e}", file=sys.stderr)
        sys.exit(1)

    print(f"[SFTPGo] Found {len(sftpgo_users)} users")

    # Connect to Momentry DB and set schema
    conn = psycopg2.connect(args.db)
    cur = conn.cursor()
    cur.execute("SET search_path TO dev")

    synced = 0
    skipped = 0

    for user in sftpgo_users:
        username = user.get("username")
        status = user.get("status", 0)

        if not username or status != 1:
            skipped += 1
            continue

        role = "admin" if username == "admin" else "user"
        # Placeholder hash — will be updated on first login via SFTPGo fallback
        placeholder_hash = "$placeholder$synced_from_sftpgo"

        if args.dry_run:
            print(f"  Would insert: {username} (role={role})")
            synced += 1
            continue

        try:
            cur.execute(
                "INSERT INTO users (username, password_hash, role) VALUES (%s, %s, %s) "
                "ON CONFLICT (username) DO NOTHING",
                (username, placeholder_hash, role),
            )
            if cur.rowcount > 0:
                print(f"  ✅ {username} (role={role})")
                synced += 1
            else:
                print(f"  ⏭️  {username} already exists, skipped")
                skipped += 1
        except Exception as e:
            print(f"  ❌ {username}: {e}", file=sys.stderr)
            skipped += 1

    conn.commit()
    cur.close()
    conn.close()

    print(f"\nDone: {synced} synced, {skipped} skipped/errors")
    print("Note: Password hashes are placeholders. First login via Momentry will cache the real hash.")


if __name__ == "__main__":
    main()
