#!/usr/bin/env python3
import os
import sys
import json
import requests
from urllib.parse import quote

# ---------------- .env loading (KEY=VALUE; quotes supported) ----------------
def _strip_quotes(val: str) -> str:
    val = val.strip()
    if len(val) >= 2 and (val[0] == val[-1]) and val[0] in ("'", '"'):
        return val[1:-1]
    return val

def _load_env_file(path: str) -> None:
    if not os.path.exists(path):
        return
    with open(path, "r", encoding="utf-8") as f:
        for raw in f:
            s = raw.strip()
            if not s or s.startswith("#"):
                continue
            if "=" not in s:
                continue
            k, v = s.split("=", 1)
            k = k.strip()
            v = _strip_quotes(v)
            if k and k not in os.environ:
                os.environ[k] = v

def load_env():
    """Load .env from script dir then CWD; no 'export' needed."""
    script_dir = os.path.dirname(os.path.abspath(__file__))
    for p in (os.path.join(script_dir, ".env"), os.path.join(os.getcwd(), ".env")):
        _load_env_file(p)

load_env()

# ---------------- Config ----------------
OKTA_DOMAIN = os.getenv("OKTA_DOMAIN")                 # e.g., "gallaudet.okta.com"
API_TOKEN   = os.getenv("OKTA_API_TOKEN")              # required
APP_ID      = os.getenv("OKTA_APP_ID")                 # required: the target Okta appId
DEFAULT_EMAIL_DOMAIN = os.getenv("DEFAULT_EMAIL_DOMAIN", "gallaudet.edu")

if not (OKTA_DOMAIN and API_TOKEN and APP_ID):
    sys.stderr.write(
        "ERROR: Missing required settings. Ensure your .env contains:\n"
        "  OKTA_DOMAIN=\"gallaudet.okta.com\"\n"
        "  OKTA_API_TOKEN=\"xxxxx\"\n"
        "  OKTA_APP_ID=\"0oa...\"\n"
        "Optional:\n"
        "  DEFAULT_EMAIL_DOMAIN=\"gallaudet.edu\"\n"
    )
    sys.exit(1)

BASE_URL   = f"https://{OKTA_DOMAIN}"
USERS_URL  = f"{BASE_URL}/api/v1/users"
APPS_URL   = f"{BASE_URL}/api/v1/apps"

# ---------------- HTTP helper ----------------
def req(method, url, **kw):
    headers = kw.pop("headers", {})
    headers["Authorization"] = f"SSWS {API_TOKEN}"
    headers["Accept"] = "application/json"
    return requests.request(method, url, headers=headers, timeout=15, **kw)

# ---------------- Args ----------------
if len(sys.argv) != 2:
    print(f"Usage: {sys.argv[0]} <USER_ID_or_LOGIN>")
    print("Examples:")
    print(f"  {sys.argv[0]} 00u1abcdE2FGHIJKL3p4")
    print(f"  {sys.argv[0]} jared.evans@gallaudet.edu")
    print(f"  {sys.argv[0]} jared.evans   # will append @{DEFAULT_EMAIL_DOMAIN}")
    sys.exit(1)

user_arg = sys.argv[1]

def normalize_login(s: str) -> str:
    return s if "@" in s else f"{s}@{DEFAULT_EMAIL_DOMAIN}"

# ---------------- Okta helpers ----------------
def find_user_id_by_login(login: str):
    r = req("GET", USERS_URL, params={"filter": f'profile.login eq "{login}"', "limit": "1"})
    if r.status_code != 200:
        raise RuntimeError(f"User lookup error {r.status_code}: {r.text}")
    data = r.json()
    if isinstance(data, list) and data:
        return data[0].get("id"), data[0]
    return None, None

def get_app_user_assignment(app_id: str, user_id: str) -> requests.Response:
    url = f"{APPS_URL}/{quote(app_id)}/users/{quote(user_id)}"
    return req("GET", url)

# ---------------- Main flow ----------------
# Resolve user id if needed
if user_arg.startswith("00u"):   # looks like an Okta user id
    user_id = user_arg
    resolved_login = None
else:
    login = normalize_login(user_arg)
    user_id, user_obj = find_user_id_by_login(login)
    if not user_id:
        print(f"User not found for login '{login}'.")
        sys.exit(1)
    resolved_login = login
    print(f"Resolved login '{login}' to Okta user id: {user_id}")

# Fetch assignment for the fixed app
resp = get_app_user_assignment(APP_ID, user_id)

if resp.status_code == 200:
    print(json.dumps(resp.json(), indent=2))
    sys.exit(0)

# Helpful diagnostics
if resp.status_code == 404:
    # 404 can mean: user not assigned to app, bad app id, or masked permission issue
    app_check = req("GET", f"{APPS_URL}/{quote(APP_ID)}")
    if app_check.status_code == 404:
        print(f"App not found: appId '{APP_ID}'.")
    elif app_check.status_code == 200:
        who = resolved_login or user_id
        print(f"User '{who}' (id {user_id}) is likely NOT assigned to app '{APP_ID}', or you lack permission.")
    else:
        print(f"Assignment 404; app check returned {app_check.status_code}: {app_check.text}")
    sys.exit(1)

print(f"Error {resp.status_code}: {resp.text}")
sys.exit(1)
