"""
Bootstrap operations for initial system setup.
"""

from datetime import UTC, datetime

import uuid7

import paskia.db.operations as _ops
from paskia.authsession import reset_expires
from paskia.db.structs import Config, Org, Permission, ResetToken, Role, User
from paskia.util.crypto import secret_key


def bootstrap(
    org_name: str = "Organization",
    admin_name: str = "Admin",
    reset_passphrase: str | None = None,
    reset_expiry: datetime | None = None,
    config: Config | None = None,
) -> str:
    """Bootstrap the entire system in a single transaction.

    Creates:
    - auth:admin permission (Master Admin)
    - auth:org:admin permission (Org Admin)
    - Organization with Administration role
    - Admin user with Administration role
    - Reset token for admin registration
    - Config (if provided)

    This is the only way to create a new database file.
    All data is created atomically - if any step fails, nothing is written.

    Args:
        org_name: Display name for the organization (default: "Organization")
        admin_name: Display name for the admin user (default: "Admin")
        reset_passphrase: Passphrase for the reset token (generated if not provided)
        reset_expiry: Expiry datetime for the reset token (default: 14 days)
        config: Configuration to store (rp_id, rp_name, origins, etc.)

    Returns:
        The reset passphrase for admin registration.
    """

    # Check if system is already bootstrapped
    for p in _ops._db.permissions.values():
        if p.scope == "auth:admin":
            raise ValueError(
                "System already bootstrapped (auth:admin permission exists)"
            )

    # Generate UUIDs upfront
    now = datetime.now(UTC)
    perm_admin_uuid = uuid7.create(now)
    perm_org_admin_uuid = uuid7.create(now)
    org_uuid = uuid7.create(now)
    role_uuid = uuid7.create(now)
    user_uuid = uuid7.create(now)

    # Set reset token expiry (passphrase generated by ResetToken.create)
    if reset_expiry is None:
        reset_expiry = reset_expires()

    with _ops._db.transaction("bootstrap"):
        # Create auth:admin permission
        perm_admin = Permission(
            scope="auth:admin",
            display_name="Master Admin",
            orgs={org_uuid: True},  # Grant to org
        )
        perm_admin.uuid = perm_admin_uuid
        perm_admin.store()

        # Create auth:org:admin permission
        perm_org_admin = Permission(
            scope="auth:org:admin",
            display_name="Org Admin",
            orgs={org_uuid: True},  # Grant to org
        )
        perm_org_admin.uuid = perm_org_admin_uuid
        perm_org_admin.store()

        # Create organization
        new_org = Org.create(display_name=org_name)
        new_org.uuid = org_uuid
        new_org.store()

        # Create Administration role with both permissions
        admin_role = Role(
            org_uuid=org_uuid,
            display_name="Administration",
            permissions={perm_admin_uuid: True, perm_org_admin_uuid: True},
        )
        admin_role.uuid = role_uuid
        admin_role.store()

        # Create admin user
        admin_user = User(
            display_name=admin_name,
            role_uuid=role_uuid,
            created_at=now,
            last_seen=None,
            visits=0,
            theme="",
        )
        admin_user.uuid = user_uuid
        admin_user.store()

        # Create reset token
        reset_token, reset_passphrase = ResetToken.create(
            user=user_uuid,
            expiry=reset_expiry,
            token_type="admin bootstrap",
            passphrase=reset_passphrase,
        )
        reset_token.store()

        # Set config if provided
        if config is not None:
            _ops._db.config = config

        # Generate OIDC signing key
        _ops._db.oidc.key = secret_key()

    return reset_passphrase
