#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
#  Caddy Manager  –  gum-powered TUI
#  SSH target : root@192.168.0.17
#  Sites dir  : ~/sites
# ─────────────────────────────────────────────────────────────

set -uo pipefail

SSH_TARGET="root@192.168.0.17"
SITES_DIR="~/sites"
RELOAD_CMD="docker exec -w /etc/caddy caddy caddy reload"

# ── Colour palette ────────────────────────────────────────────
ORANGE="#FF6B00"
ORANGE_DIM="#CC5500"
GREY_DARK="#2A2A2A"
GREY_MID="#4A4A4A"
GREY_LIGHT="#AAAAAA"
WHITE="#F5F5F5"

# ── Dependency check ─────────────────────────────────────────
if ! command -v gum &>/dev/null; then
    echo "ERROR: 'gum' is not installed."
    exit 1
fi

if ! command -v ssh &>/dev/null; then
    echo "ERROR: 'ssh' is not installed."
    exit 1
fi

# ── Helpers ───────────────────────────────────────────────────

draw_title() {
    clear
    gum style \
        --foreground "$ORANGE" \
        --border-foreground "$ORANGE" \
        --border double \
        --align center \
        --width 50 \
        --margin "1 2" \
        --padding "1 4" \
        --bold \
        "⚙  CADDY MANAGER  ⚙" \
        "" \
        "$(gum style --foreground "$GREY_LIGHT" --faint "$(date '+%a %d %b %Y  %H:%M')")"
}

ssh_run() {
    # Run a command on the remote host
    ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_TARGET" "$@"
}

reload_caddy() {
    gum spin \
        --spinner dot \
        --title "Reloading Caddy..." \
        --title.foreground "$ORANGE" \
        -- ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_TARGET" "$RELOAD_CMD"
}

press_enter() {
    echo ""
    gum style --foreground "$GREY_LIGHT" "Press Enter to return to the menu..."
    read -r
}

# ── Option 1 – Add a new config ───────────────────────────────

add_config() {
    draw_title
    gum style \
        --foreground "$ORANGE" \
        --bold \
        --margin "0 2" \
        "  ADD NEW SITE CONFIG"
    echo ""

    # Service name (used as filename)
    SERVICE=$(gum input \
        --prompt "  Service name (filename):  " \
        --prompt.foreground "$ORANGE" \
        --placeholder "e.g. nextcloud" \
        --width 40 \
        --cursor.foreground "$ORANGE")

    [[ -z "$SERVICE" ]] && { gum style --foreground "red" "  Aborted – no service name given."; press_enter; return; }

    # Domain – type subdomain only, suffix appended automatically
    SUBDOMAIN=$(gum input \
        --prompt "  Subdomain:                 " \
        --prompt.foreground "$ORANGE" \
        --placeholder "e.g. homarr  (will become homarr.marlow.quest)" \
        --width 50 \
        --cursor.foreground "$ORANGE")

    [[ -z "$SUBDOMAIN" ]] && { gum style --foreground "red" "  Aborted – no domain given."; press_enter; return; }

    # If they typed a full domain (contains a dot) use as-is, otherwise append suffix
    if [[ "$SUBDOMAIN" == *.* ]]; then
        DOMAIN="$SUBDOMAIN"
    else
        DOMAIN="${SUBDOMAIN}.marlow.quest"
    fi

    gum style --foreground "$GREY_LIGHT" --margin "0 2" "  → ${DOMAIN}"
    echo ""

    # Upstream IP:port – pre-filled with common subnet prefix
    UPSTREAM=$(gum input \
        --prompt "  Upstream IP:port:          " \
        --prompt.foreground "$ORANGE" \
        --value "192.168.0." \
        --width 40 \
        --cursor.foreground "$ORANGE")

    [[ -z "$UPSTREAM" ]] && { gum style --foreground "red" "  Aborted – no upstream given."; press_enter; return; }

    # TinyAuth?
    echo ""
    gum style --foreground "$GREY_LIGHT" --margin "0 2" "  Include TinyAuth middleware?"
    USE_TINYAUTH=$(gum choose \
        --cursor "▶ " \
        --cursor.foreground "$ORANGE" \
        --selected.foreground "$ORANGE" \
        --header "  Select an option:" \
        --header.foreground "$GREY_LIGHT" \
        "No" "Yes")

    # Build the Caddy config block
    if [[ "$USE_TINYAUTH" == "Yes" ]]; then
        CONFIG_BLOCK="${DOMAIN} {
    import tinyauth

    reverse_proxy ${UPSTREAM}
}"
    else
        CONFIG_BLOCK="${DOMAIN} {
    reverse_proxy ${UPSTREAM}
}"
    fi

    # Preview
    echo ""
    gum style \
        --foreground "$ORANGE" \
        --border normal \
        --border-foreground "$GREY_MID" \
        --padding "1 2" \
        --margin "0 2" \
        "$CONFIG_BLOCK"
    echo ""

    gum confirm \
        --prompt.foreground "$ORANGE" \
        --selected.background "$ORANGE" \
        --selected.foreground "$GREY_DARK" \
        "  Write ${SERVICE}.conf to ${SITES_DIR} and reload Caddy?" \
    || { gum style --foreground "$GREY_LIGHT" "  Cancelled."; press_enter; return; }

    # Write file via SSH heredoc
    ssh_run "cat > ${SITES_DIR}/${SERVICE}.conf" <<EOF
${CONFIG_BLOCK}
EOF

    echo ""
    gum style --foreground "green" "  ✔  Config written to ${SITES_DIR}/${SERVICE}.conf"

    reload_caddy && gum style --foreground "green" "  ✔  Caddy reloaded successfully." \
                 || gum style --foreground "red"   "  ✗  Caddy reload failed – check logs."
    press_enter
}

# ── Option 2 – List / view configs ───────────────────────────

list_configs() {
    while true; do
        draw_title
        gum style \
            --foreground "$ORANGE" \
            --bold \
            --margin "0 2" \
            "  SITE CONFIGS"
        echo ""

        # Fetch all file names
        mapfile -t FILES < <(ssh_run "ls ${SITES_DIR}/" 2>/dev/null || true)

        # Remove blank entries
        CLEAN_FILES=()
        for f in "${FILES[@]+"${FILES[@]}"}"; do
            [[ -n "$f" ]] && CLEAN_FILES+=("$f")
        done

        if [[ ${#CLEAN_FILES[@]} -eq 0 ]]; then
            gum style --foreground "$GREY_LIGHT" --margin "0 2" \
                "  No config files found in ${SITES_DIR}/"
            press_enter
            return
        fi

        # Parse each file individually — build display arrays and a lookup map
        T_NAME=()
        T_DOMAIN=()
        T_UPSTREAM=()
        T_TINYAUTH=()

        for FILE in "${CLEAN_FILES[@]}"; do
            FILE_CONTENT=$(ssh_run "cat ${SITES_DIR}/${FILE}" 2>/dev/null || true)

            DOMAIN=$(echo "$FILE_CONTENT" \
                | grep -v '^\s*#' | grep -v '^\s*$' | grep -v '^\s' \
                | grep '\.' | head -1 | awk '{print $1}' | tr -d '{}' || true)
            [[ -z "$DOMAIN" ]] && DOMAIN="—"

            UPSTREAM=$(echo "$FILE_CONTENT" \
                | grep -i 'reverse_proxy' | awk '{print $2}' | head -1 || true)
            [[ -z "$UPSTREAM" ]] && UPSTREAM="—"

            if echo "$FILE_CONTENT" | grep -qi 'tinyauth' 2>/dev/null; then
                TA="yes"
            else
                TA="no"
            fi

            T_NAME+=("$FILE")
            T_DOMAIN+=("$DOMAIN")
            T_UPSTREAM+=("$UPSTREAM")
            T_TINYAUTH+=("$TA")
        done

        # Write CSV to temp file (gum table needs a real fd, not a pipe)
        TMPCSV=$(mktemp /tmp/caddy-XXXXXX.csv)
        for i in "${!T_NAME[@]}"; do
            printf '%s,%s,%s,%s\n' \
                "${T_NAME[$i]}" "${T_DOMAIN[$i]}" "${T_UPSTREAM[$i]}" "${T_TINYAUTH[$i]}" \
                >> "$TMPCSV"
        done

        gum style --foreground "$GREY_LIGHT" --margin "0 2" \
            "  ↑↓ navigate · Enter to view full config · Esc to go back"
        echo ""

        SELECTED=$(gum table \
            --columns "FILE,DOMAIN,UPSTREAM,TINYAUTH" \
            --widths "26,30,22,9" \
            --height 18 \
            --border.foreground "$ORANGE" \
            --header.foreground "$ORANGE" \
            --selected.foreground "$GREY_DARK" \
            --selected.background "$ORANGE" \
            < "$TMPCSV" || true)

        rm -f "$TMPCSV"

        [[ -z "$SELECTED" ]] && return

        # Extract filename from first CSV column
        CHOICE=$(echo "$SELECTED" | cut -d',' -f1 | xargs)

        # ── Show full file contents ────────────────────────────
        clear
        gum style \
            --foreground "$ORANGE" \
            --bold \
            --margin "1 2 0 2" \
            "  ▸ ${CHOICE}"
        echo ""

        CONTENT=$(ssh_run "cat ${SITES_DIR}/${CHOICE}" 2>/dev/null || true)
        [[ -z "$CONTENT" ]] && CONTENT="(unable to read file)"

        gum style \
            --foreground "$WHITE" \
            --border normal \
            --border-foreground "$GREY_MID" \
            --padding "1 2" \
            --margin "0 2" \
            "$CONTENT"

        echo ""
        press_enter
    done
}

# ── Option 3 – Delete a config ────────────────────────────────

delete_config() {
    draw_title
    gum style \
        --foreground "$ORANGE" \
        --bold \
        --margin "0 2" \
        "  DELETE SITE CONFIG"
    echo ""

    # Fetch file list
    mapfile -t FILES < <(ssh_run "ls ${SITES_DIR}/" 2>/dev/null | sort)

    if [[ ${#FILES[@]} -eq 0 ]]; then
        gum style --foreground "$GREY_LIGHT" --margin "0 2" "  No config files found in ${SITES_DIR}/"
        press_enter
        return
    fi

    CHOICE=$(printf '%s\n' "${FILES[@]}" "── Cancel ──" | \
        gum choose \
            --cursor "▶ " \
            --cursor.foreground "$ORANGE" \
            --selected.foreground "red" \
            --header "  Select a config to delete:" \
            --header.foreground "$GREY_LIGHT" \
            --height 15)

    [[ "$CHOICE" == "── Cancel ──" || -z "$CHOICE" ]] && { gum style --foreground "$GREY_LIGHT" "  Cancelled."; press_enter; return; }

    echo ""

    # Show contents before confirming
    CONTENT=$(ssh_run "cat ${SITES_DIR}/${CHOICE}" 2>/dev/null || echo "(unable to read file)")
    gum style \
        --foreground "$GREY_LIGHT" \
        --border normal \
        --border-foreground "red" \
        --padding "1 2" \
        --margin "0 2" \
        "$CONTENT"
    echo ""

    gum confirm \
        --prompt.foreground "$ORANGE" \
        --selected.background "$ORANGE" \
        --selected.foreground "$GREY_DARK" \
        "  Permanently delete ${CHOICE} and reload Caddy?" \
    || { gum style --foreground "$GREY_LIGHT" "  Cancelled."; press_enter; return; }

    ssh_run "rm -f ${SITES_DIR}/${CHOICE}"

    echo ""
    gum style --foreground "green" "  ✔  Deleted ${SITES_DIR}/${CHOICE}"

    reload_caddy && gum style --foreground "green" "  ✔  Caddy reloaded successfully." \
                 || gum style --foreground "red"   "  ✗  Caddy reload failed – check logs."
    press_enter
}

# ── Main menu loop ────────────────────────────────────────────

while true; do
    draw_title

    MENU_CHOICE=$(gum choose \
        --cursor "▶ " \
        --cursor.foreground "$ORANGE" \
        --selected.foreground "$ORANGE" \
        --header "  What would you like to do?" \
        --header.foreground "$GREY_LIGHT" \
        --height 6 \
        "  1  Add a new site config" \
        "  2  List / view site configs" \
        "  3  Delete a site config" \
        "  ✕  Exit")

    case "$MENU_CHOICE" in
        *"1"*)  add_config    ;;
        *"2"*)  list_configs  ;;
        *"3"*)  delete_config ;;
        *"✕"*|"") clear; exit 0 ;;
    esac
done
