#!/bin/bash

# Linkding stores users in standard Django auth (django.contrib.auth.models.User).
# We drive the same User model the web UI uses via `python manage.py shell -c`
# from inside the linkding-service container — password hashing and admin flags
# come out identical to what Django itself would write.
#
# Username (not email) is the primary identifier in Linkding's UI, so the Tools
# manifest, the EZ_USER\t panel rows, and every lookup here all key on username.
# Email is stored when supplied but never required.

_linkdingManage() {
    local container="linkding-service"
    local py_body="$1"
    shift
    runFileOp docker exec -i -w /etc/linkding "$@" "$container" \
        python manage.py shell -c "$py_body" 2>&1
}

authAdapter_linkding_setPassword() {
    local username="$1" password="$2"
    [[ -z "$username" ]] && { isError "Username is required."; return 1; }
    [[ -z "$password" ]] && password=$(generateRandomPassword)

    local out
    out=$(_linkdingManage '
import os
from django.contrib.auth import get_user_model
U = get_user_model()
u = U.objects.filter(username=os.environ["EZ_USER"]).first()
if not u:
    print("EZ_USER_NOT_FOUND"); raise SystemExit
u.set_password(os.environ["EZ_PASS"]); u.save()
print("EZ_RESET_OK:" + u.username)
' -e "EZ_USER=$username" -e "EZ_PASS=$password")

    if echo "$out" | grep -q EZ_USER_NOT_FOUND; then
        isError "No Linkding user '$username'."; return 1
    fi
    if ! echo "$out" | grep -q EZ_RESET_OK; then
        isError "Linkding password reset failed: $out"; return 1
    fi

    # Mirror the admin password back into the .config if we just reset the
    # account we know about — keeps the WebUI's "Admin credentials" card
    # honest. Skipped when the user resets a non-admin account.
    if [[ "$username" == "${CFG_LINKDING_ADMIN_USER:-}" ]]; then
        authPersistCfg linkding ADMIN_PASSWORD "$password"
    fi
    isSuccessful "Linkding password set for $username — New password: $password"
}

authAdapter_linkding_createUser() {
    local username="$1" password="$2" email="$3" isAdmin="$4"
    [[ -z "$username" ]] && { isError "Username is required."; return 1; }
    [[ -z "$password" ]] && password=$(generateRandomPassword)

    local make_super="False"
    [[ "$isAdmin" == "true" ]] && make_super="True"

    local out
    out=$(_linkdingManage '
import os
from django.contrib.auth import get_user_model
U = get_user_model()
if U.objects.filter(username=os.environ["EZ_USER"]).exists():
    print("EZ_USER_EXISTS"); raise SystemExit
email = os.environ.get("EZ_EMAIL", "")
if os.environ["EZ_ADMIN"] == "True":
    u = U.objects.create_superuser(
        username=os.environ["EZ_USER"],
        email=email,
        password=os.environ["EZ_PASS"],
    )
else:
    u = U.objects.create_user(
        username=os.environ["EZ_USER"],
        email=email,
        password=os.environ["EZ_PASS"],
    )
print("EZ_USER_CREATED:" + str(u.id))
' -e "EZ_USER=$username" -e "EZ_PASS=$password" -e "EZ_EMAIL=$email" -e "EZ_ADMIN=$make_super")

    if echo "$out" | grep -q EZ_USER_EXISTS; then
        isError "Linkding user '$username' already exists."; return 1
    fi
    if ! echo "$out" | grep -q EZ_USER_CREATED; then
        isError "Linkding user creation failed: $out"; return 1
    fi

    # If we just minted the first admin account, remember it so subsequent
    # password resets keep the .config in sync (same pattern bookstack uses).
    if [[ "$isAdmin" == "true" && -z "${CFG_LINKDING_ADMIN_USER:-}" ]]; then
        authPersistCfg linkding ADMIN_USER "$username"
        authPersistCfg linkding ADMIN_PASSWORD "$password"
    fi
    isSuccessful "Linkding user created — Username: $username — Password: $password"
}

authAdapter_linkding_listUsers() {
    # The user-list modal in the WebUI uses `email || username` as each row's
    # display id and pre-fills the tool's `username` field with that value
    # (via fillIdentifier in tools-manager.js). Linkding's primary id IS the
    # username and email is optional, so emit username in BOTH slots — the
    # row click then always sends back the username our other tools expect.
    # The third column (`roles`) is matched against /admin/i in the JS to
    # decide whether to show the 👑→👤 demote toggle vs 👤→👑 promote.
    _linkdingManage '
from django.contrib.auth import get_user_model
for u in get_user_model().objects.all().order_by("username"):
    if u.is_superuser: role = "admin"
    elif u.is_staff:   role = "staff"
    else:              role = "user"
    print("EZ_USER\t%s\t%s\t%s" % (u.username, u.username, role))
'
}

authAdapter_linkding_deleteUser() {
    local username="$1"
    [[ -z "$username" ]] && { isError "Username is required."; return 1; }
    local out
    out=$(_linkdingManage '
import os
from django.contrib.auth import get_user_model
u = get_user_model().objects.filter(username=os.environ["EZ_USER"]).first()
if not u:
    print("EZ_USER_NOT_FOUND"); raise SystemExit
u.delete()
print("EZ_USER_DELETED")
' -e "EZ_USER=$username")
    echo "$out" | grep -q EZ_USER_NOT_FOUND && { isError "No Linkding user '$username'."; return 1; }
    echo "$out" | grep -q EZ_USER_DELETED   || { isError "Linkding delete failed: $out"; return 1; }
    isSuccessful "Linkding user '$username' deleted."
}

authAdapter_linkding_setAdmin() {
    local username="$1" isAdmin="$2"
    [[ -z "$username" ]] && { isError "Username is required."; return 1; }
    local target="$isAdmin"
    [[ "$target" != "true" ]] && target="false"

    local out
    out=$(_linkdingManage '
import os
from django.contrib.auth import get_user_model
u = get_user_model().objects.filter(username=os.environ["EZ_USER"]).first()
if not u:
    print("EZ_USER_NOT_FOUND"); raise SystemExit
flag = os.environ["EZ_TARGET"] == "true"
u.is_superuser = flag
u.is_staff     = flag
u.save()
print("EZ_OK")
' -e "EZ_USER=$username" -e "EZ_TARGET=$target")
    echo "$out" | grep -q EZ_USER_NOT_FOUND && { isError "No Linkding user '$username'."; return 1; }
    echo "$out" | grep -q EZ_OK             || { isError "Linkding admin toggle failed: $out"; return 1; }
    isSuccessful "Linkding user '$username' admin → $target."
}
