from __future__ import annotations

import argparse
import getpass
import logging
import os
import re

from sqlalchemy import text

from app import create_app, db
from app.core.common.identifiers import new_governance_uid
from app.core.system.auth import hash_password


logger = logging.getLogger(__name__)


def validate_password(password: str) -> None:
    if len(password) < 10:
        raise ValueError("password must contain at least 10 characters")
    if not re.search(r"[a-z]", password):
        raise ValueError("password must contain a lowercase letter")
    if not re.search(r"[A-Z]", password):
        raise ValueError("password must contain an uppercase letter")
    if not re.search(r"[0-9]", password):
        raise ValueError("password must contain a digit")


def log_bootstrap_result(username: str, *, created: bool) -> None:
    if created:
        logger.info("Created first platform administrator: %s", username)
    else:
        logger.info("Platform administrator already exists; bootstrap skipped")


def bootstrap_first_admin(session, *, username: str, password: str) -> str:
    validate_password(password)
    existing = session.execute(
        text(
            "SELECT COUNT(*) FROM public.users u "
            "JOIN public.user_roles ur ON ur.user_id = u.id "
            "JOIN public.roles r ON r.id = ur.role_id "
            "WHERE r.name = 'admin' AND u.status = 'active'"
        )
    ).scalar_one()
    if existing:
        raise RuntimeError("an active administrator already exists")

    user_id = new_governance_uid()
    session.execute(
        text(
            "INSERT INTO public.users "
            "(id, username, display_name, password_hash) "
            "VALUES (CAST(:id AS uuid), :username, :username, :password_hash)"
        ),
        {"id": user_id, "username": username.strip(), "password_hash": hash_password(password)},
    )
    session.execute(
        text(
            "INSERT INTO public.user_roles (user_id, role_id, assigned_by) "
            "SELECT CAST(:id AS uuid), id, CAST(:id AS uuid) "
            "FROM public.roles WHERE name = 'admin'"
        ),
        {"id": user_id},
    )
    return user_id


def main() -> None:
    parser = argparse.ArgumentParser(description="Create the first DataOps administrator")
    parser.add_argument("--username", default=os.environ.get("BOOTSTRAP_ADMIN_USERNAME"))
    parser.add_argument("--password", default=os.environ.get("BOOTSTRAP_ADMIN_PASSWORD"))
    parser.add_argument("--if-missing", action="store_true")
    args = parser.parse_args()
    username = args.username or input("Administrator username: ").strip()
    password = args.password or getpass.getpass("Administrator password: ")

    app = create_app()
    with app.app_context():
        try:
            bootstrap_first_admin(db.session, username=username, password=password)
            db.session.commit()
            log_bootstrap_result(username, created=True)
        except RuntimeError:
            db.session.rollback()
            if not args.if_missing:
                raise
            log_bootstrap_result(username, created=False)


if __name__ == "__main__":
    main()
