#!/bin/bash
# kioskvis - Kiosk Visibility Management Tool
# Manage roomset visibility and session timeouts for ISA kiosk mode
# via visibleRoomsets.json
#
# Usage:
#   kioskvis ls                    - List all roomsets with their visibility status
#   kioskvis enable <id>           - Enable visibility for a roomset (by openapi_id or isacore_id)
#   kioskvis disable <id>          - Disable visibility for a roomset
#   kioskvis timeouts              - Show session timeout settings
#   kioskvis set-timeout <min|none>          - Machine-wide inactivity timeout
#   kioskvis set-user-timeout <user> <min|none> - Per-user inactivity timeout
#   kioskvis del-user-timeout <user>         - Drop a per-user timeout
#   kioskvis show                  - Show the raw JSON configuration
#   kioskvis path                  - Show the configuration file path

set -e

# Determine config file path (same logic as Flutter app)
if [ -n "$HOME" ]; then
    CONFIG_FILE="$HOME/visibleRoomsets.json"
else
    CONFIG_FILE="/root/visibleRoomsets.json"
fi

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Check if jq is installed
if ! command -v jq &> /dev/null; then
    echo -e "${RED}Error: jq is required but not installed.${NC}"
    echo "Install it with: apt-get install jq"
    exit 1
fi

# Function to display usage
usage() {
    cat << EOF
kioskvis - Kiosk Visibility Management Tool

Usage:
  kioskvis ls                    List all roomsets with visibility status
  kioskvis enable <id>           Enable visibility for a roomset
  kioskvis disable <id>          Disable visibility for a roomset

Session timeout (inactivity before auto-logout), in MINUTES:
  kioskvis timeouts                            Show all timeout settings
  kioskvis set-timeout <minutes|none>          Machine-wide setting
  kioskvis set-user-timeout <user> <min|none>  Per-user setting
  kioskvis del-user-timeout <user>             Drop a per-user setting

  kioskvis show                  Show raw JSON configuration
  kioskvis path                  Show configuration file path
  kioskvis help                  Show this help message

Arguments:
  <id>         Can be either openapi_id or isacore_id of the roomset
  <user>       Email or username
  <minutes>    Whole number of minutes, >= 1. Use "none" (or 0) to clear the
               setting and fall back to the next level.

Timeout precedence, most specific first:
  1. per-user setting here          (set-user-timeout)
  2. machine-wide setting here      (set-timeout)
  3. per-organization ISACore licensing override
  4. built-in 10-minute RGPD default

Examples:
  kioskvis ls
  kioskvis enable 63bc00f4bcfb27edf14ae5be
  kioskvis disable f8d3e4a2-1b2c-4d5e-9f8a-7b6c5d4e3f2a
  kioskvis set-timeout 30                      # 30 min for this machine
  kioskvis set-timeout none                    # back to org / default
  kioskvis set-user-timeout 6f@chmouscron.be 480
  kioskvis del-user-timeout 6f@chmouscron.be

Changes apply within ~5s: the app polls this file, no restart needed.

Configuration file: $CONFIG_FILE
EOF
}

# Function to check if config file exists
check_config() {
    if [ ! -f "$CONFIG_FILE" ]; then
        echo -e "${RED}Error: Configuration file not found: $CONFIG_FILE${NC}"
        echo "The file will be created automatically by the kiosk application on first run."
        exit 1
    fi
}

# Function to list all roomsets
cmd_ls() {
    check_config

    echo -e "${BLUE}Organization:${NC} $(jq -r '.organizationLabel // "Unknown"' "$CONFIG_FILE")"
    echo -e "${BLUE}Last Updated:${NC} $(jq -r '.lastUpdated // "Unknown"' "$CONFIG_FILE")"
    echo ""
    echo -e "${BLUE}Roomsets:${NC}"
    echo "─────────────────────────────────────────────────────────────────────────────"

    jq -r '.roomsets[] |
        "\(.visible)|\(.label)|\(.openapi_id // "null")|\(.isacore_id // "null")"' "$CONFIG_FILE" | \
    while IFS='|' read -r visible label openapi_id isacore_id; do
        if [ "$visible" = "true" ]; then
            status="${GREEN}✓ VISIBLE${NC}"
        else
            status="${RED}✗ HIDDEN${NC}"
        fi

        echo -e "$status  ${YELLOW}$label${NC}"
        echo "          OpenAPI: $openapi_id"
        echo "          IsaCore: $isacore_id"
        echo ""
    done
}

# Function to enable/disable a roomset
cmd_set_visibility() {
    local id="$1"
    local new_visibility="$2"

    check_config

    if [ -z "$id" ]; then
        echo -e "${RED}Error: No ID provided${NC}"
        echo "Usage: kioskvis enable|disable <id>"
        exit 1
    fi

    # Check if ID exists and update visibility
    local updated=false
    local label=""

    # Use jq to update the visibility
    local temp_file=$(mktemp)
    jq --arg id "$id" --argjson vis "$new_visibility" '
        .roomsets |= map(
            if (.openapi_id == $id or .isacore_id == $id) then
                .visible = $vis
            else
                .
            end
        ) |
        .lastUpdated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
    ' "$CONFIG_FILE" > "$temp_file"

    # Check if any change was made
    label=$(jq -r --arg id "$id" '.roomsets[] | select(.openapi_id == $id or .isacore_id == $id) | .label' "$temp_file")

    if [ -z "$label" ]; then
        echo -e "${RED}Error: No roomset found with ID: $id${NC}"
        echo "Use 'kioskvis ls' to see all available roomsets"
        rm "$temp_file"
        exit 1
    fi

    # Move temp file to actual config
    mv "$temp_file" "$CONFIG_FILE"

    if [ "$new_visibility" = "true" ]; then
        echo -e "${GREEN}✓ Enabled visibility for: $label${NC}"
    else
        echo -e "${YELLOW}✗ Disabled visibility for: $label${NC}"
    fi

    echo "Configuration updated: $CONFIG_FILE"
}

# Function to show raw JSON
cmd_show() {
    check_config
    jq '.' "$CONFIG_FILE"
}

# Function to show config path
cmd_path() {
    echo "$CONFIG_FILE"
    if [ -f "$CONFIG_FILE" ]; then
        echo -e "${GREEN}File exists${NC}"
    else
        echo -e "${RED}File does not exist${NC}"
    fi
}

# Parse a minutes argument.
# Echoes the whole number of minutes, or "null" for none/0/empty.
# Exits non-zero on anything else so callers can bail out.
parse_minutes() {
    local raw="$1"
    case "$raw" in
        none|None|NONE|null|NULL|default|"")
            echo "null"; return 0 ;;
    esac
    if ! [[ "$raw" =~ ^[0-9]+$ ]]; then
        echo -e "${RED}Error: minutes must be a whole number, or 'none' to clear${NC}" >&2
        return 1
    fi
    # 0 means "no setting" — same as none, keeps the JSON free of dead entries.
    if [ "$raw" -eq 0 ]; then echo "null"; return 0; fi
    echo "$raw"
}

# Rewrite the config through jq, atomically.
# Keeps every other key untouched — roomset visibility above all.
apply_jq() {
    local temp_file
    temp_file=$(mktemp)
    if ! jq "$@" "$CONFIG_FILE" > "$temp_file"; then
        echo -e "${RED}Error: failed to update configuration${NC}" >&2
        rm -f "$temp_file"
        exit 1
    fi
    # Refuse to install an empty/!invalid result over a working config.
    if [ ! -s "$temp_file" ]; then
        echo -e "${RED}Error: refusing to write an empty configuration${NC}" >&2
        rm -f "$temp_file"
        exit 1
    fi
    mv "$temp_file" "$CONFIG_FILE"
}

# Function to show session timeout settings
cmd_timeouts() {
    check_config

    local machine
    machine=$(jq -r '.sessionTimeoutMinutes // empty' "$CONFIG_FILE")

    echo -e "${BLUE}Session timeout (inactivity before auto-logout)${NC}"
    echo "─────────────────────────────────────────────────────────────────────────────"

    if [ -z "$machine" ]; then
        echo -e "Machine-wide: ${YELLOW}not set${NC}  (falls back to org override, then 10 min)"
    else
        echo -e "Machine-wide: ${GREEN}${machine} min${NC}"
    fi
    echo ""

    local count
    count=$(jq -r '.userSessionTimeouts // {} | length' "$CONFIG_FILE")
    if [ "$count" -eq 0 ]; then
        echo -e "${BLUE}Per-user:${NC} ${YELLOW}none configured${NC}"
    else
        echo -e "${BLUE}Per-user:${NC}"
        jq -r '.userSessionTimeouts // {} | to_entries[] | "\(.key)|\(.value)"' "$CONFIG_FILE" | \
        while IFS='|' read -r user minutes; do
            if [ "$minutes" = "null" ]; then
                echo -e "  ${YELLOW}○${NC} $user — not set (falls back to machine-wide)"
            else
                echo -e "  ${GREEN}✓${NC} $user — ${GREEN}${minutes} min${NC}"
            fi
        done
        echo ""
        echo -e "${BLUE}Total:${NC} $count user setting(s)"
    fi

    echo ""
    echo "Precedence: per-user > machine-wide > org licensing override > 10 min default"
}

# Function to set the machine-wide timeout
cmd_set_timeout() {
    check_config

    local minutes
    minutes=$(parse_minutes "${1-}") || exit 1

    if [ "$minutes" = "null" ]; then
        apply_jq '
            del(.sessionTimeoutMinutes) |
            .lastUpdated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
        '
        echo -e "${YELLOW}✗ Cleared machine-wide timeout${NC} (falls back to org override, then 10 min)"
    else
        apply_jq --argjson m "$minutes" '
            .sessionTimeoutMinutes = $m |
            .lastUpdated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
        '
        echo -e "${GREEN}✓ Machine-wide timeout set to ${minutes} min${NC}"
    fi
    echo "Configuration updated: $CONFIG_FILE (applies within ~5s)"
}

# Function to set a per-user timeout
cmd_set_user_timeout() {
    local username="$1"
    check_config

    if [ -z "$username" ]; then
        echo -e "${RED}Error: No user provided${NC}"
        echo "Usage: kioskvis set-user-timeout <user> <minutes|none>"
        exit 1
    fi

    local minutes
    minutes=$(parse_minutes "${2-}") || exit 1

    # Lowercase the key: the app matches identities case-insensitively.
    local key
    key=$(echo "$username" | tr '[:upper:]' '[:lower:]')

    if [ "$minutes" = "null" ]; then
        apply_jq --arg user "$key" '
            .userSessionTimeouts = ((.userSessionTimeouts // {}) | del(.[$user])) |
            .lastUpdated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
        '
        echo -e "${YELLOW}✗ Cleared timeout for: $key${NC} (falls back to machine-wide)"
    else
        apply_jq --arg user "$key" --argjson m "$minutes" '
            .userSessionTimeouts = ((.userSessionTimeouts // {}) | .[$user] = $m) |
            .lastUpdated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
        '
        echo -e "${GREEN}✓ Timeout for $key set to ${minutes} min${NC}"
    fi
    echo "Configuration updated: $CONFIG_FILE (applies within ~5s)"
}

# Function to delete a per-user timeout
cmd_del_user_timeout() {
    local username="$1"
    check_config

    if [ -z "$username" ]; then
        echo -e "${RED}Error: No user provided${NC}"
        echo "Usage: kioskvis del-user-timeout <user>"
        exit 1
    fi

    local key
    key=$(echo "$username" | tr '[:upper:]' '[:lower:]')

    local exists
    exists=$(jq -r --arg user "$key" '(.userSessionTimeouts // {}) | has($user)' "$CONFIG_FILE")
    if [ "$exists" != "true" ]; then
        echo -e "${RED}Error: No timeout configured for: $key${NC}"
        echo "Use 'kioskvis timeouts' to see all settings"
        exit 1
    fi

    cmd_set_user_timeout "$username" none
}

# Main command dispatcher
case "${1:-}" in
    ls|list)
        cmd_ls
        ;;
    enable)
        cmd_set_visibility "$2" "true"
        ;;
    disable)
        cmd_set_visibility "$2" "false"
        ;;
    timeouts|timeout)
        cmd_timeouts
        ;;
    set-timeout)
        cmd_set_timeout "${2-}"
        ;;
    set-user-timeout)
        cmd_set_user_timeout "${2-}" "${3-}"
        ;;
    del-user-timeout)
        cmd_del_user_timeout "${2-}"
        ;;
    show)
        cmd_show
        ;;
    path)
        cmd_path
        ;;
    help|--help|-h)
        usage
        ;;
    "")
        usage
        exit 1
        ;;
    *)
        echo -e "${RED}Error: Unknown command: $1${NC}"
        echo ""
        usage
        exit 1
        ;;
esac
