"""Inspect + patch Keycloak realm token lifespans for longer sessions."""
from __future__ import annotations

import json
import os
import sys

import httpx

KEYCLOAK_URL = os.getenv("KEYCLOAK_SERVER_URL", "http://127.0.0.1:8080")
REALM = os.getenv("KEYCLOAK_REALM", "superapp")
ADMIN_USER = os.getenv("KEYCLOAK_ADMIN", "admin")
ADMIN_PASS = os.getenv("KEYCLOAK_ADMIN_PASSWORD", "admin")

# Access token: 12 hours (still refreshed proactively by FE)
ACCESS_TOKEN_LIFESPAN = int(os.getenv("KC_ACCESS_TOKEN_LIFESPAN", str(12 * 3600)))
# SSO idle: 7 days — refresh keeps working while user is inactive within this
SSO_IDLE = int(os.getenv("KC_SSO_IDLE", str(7 * 24 * 3600)))
# SSO max: 14 days absolute session ceiling
SSO_MAX = int(os.getenv("KC_SSO_MAX", str(14 * 24 * 3600)))
# Client session idle/max (refresh token bound)
CLIENT_SESSION_IDLE = SSO_IDLE
CLIENT_SESSION_MAX = SSO_MAX


def admin_token(client: httpx.Client) -> str:
    r = client.post(
        f"{KEYCLOAK_URL}/realms/master/protocol/openid-connect/token",
        data={
            "grant_type": "password",
            "client_id": "admin-cli",
            "username": ADMIN_USER,
            "password": ADMIN_PASS,
        },
    )
    r.raise_for_status()
    return r.json()["access_token"]


def main() -> int:
    apply = "--apply" in sys.argv
    with httpx.Client(timeout=20.0) as client:
        token = admin_token(client)
        headers = {"Authorization": f"Bearer {token}"}
        realm_url = f"{KEYCLOAK_URL}/admin/realms/{REALM}"
        r = client.get(realm_url, headers=headers)
        r.raise_for_status()
        realm = r.json()
        before = {
            "accessTokenLifespan": realm.get("accessTokenLifespan"),
            "ssoSessionIdleTimeout": realm.get("ssoSessionIdleTimeout"),
            "ssoSessionMaxLifespan": realm.get("ssoSessionMaxLifespan"),
            "clientSessionIdleTimeout": realm.get("clientSessionIdleTimeout"),
            "clientSessionMaxLifespan": realm.get("clientSessionMaxLifespan"),
            "offlineSessionIdleTimeout": realm.get("offlineSessionIdleTimeout"),
        }
        print("BEFORE:", json.dumps(before, indent=2))

        if not apply:
            print("Dry-run only. Pass --apply to update.")
            return 0

        realm["accessTokenLifespan"] = ACCESS_TOKEN_LIFESPAN
        realm["ssoSessionIdleTimeout"] = SSO_IDLE
        realm["ssoSessionMaxLifespan"] = SSO_MAX
        realm["clientSessionIdleTimeout"] = CLIENT_SESSION_IDLE
        realm["clientSessionMaxLifespan"] = CLIENT_SESSION_MAX
        # Keep offline sessions usable for long-lived refresh if issued
        realm["offlineSessionIdleTimeout"] = max(
            int(realm.get("offlineSessionIdleTimeout") or 0), SSO_MAX
        )

        put = client.put(realm_url, headers=headers, json=realm)
        put.raise_for_status()

        after = client.get(realm_url, headers=headers).json()
        print(
            "AFTER:",
            json.dumps(
                {
                    "accessTokenLifespan": after.get("accessTokenLifespan"),
                    "ssoSessionIdleTimeout": after.get("ssoSessionIdleTimeout"),
                    "ssoSessionMaxLifespan": after.get("ssoSessionMaxLifespan"),
                    "clientSessionIdleTimeout": after.get("clientSessionIdleTimeout"),
                    "clientSessionMaxLifespan": after.get("clientSessionMaxLifespan"),
                    "offlineSessionIdleTimeout": after.get("offlineSessionIdleTimeout"),
                },
                indent=2,
            ),
        )
        print("OK realm token lifespans updated")
        return 0


if __name__ == "__main__":
    raise SystemExit(main())
