#!/usr/bin/env bash
# ProGit Sovereign Installer
# One-line install: curl -fsSL https://progit.dev/install.sh | sh
#
# Detects OS/arch, downloads signed binary from Forgejo releases,
# verifies minisign signature, installs to ~/.local/bin or /usr/local/bin.

set -euo pipefail

REPO="ProGit/progit"
FORGEJO_HOST="${PROGIT_HOST:-git.sovereign-society.org}"
API_URL="https://${FORGEJO_HOST}/api/v1/repos/${REPO}"

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

say() { echo -e "${BLUE}[progit]${NC} $*"; }
warn() { echo -e "${YELLOW}[progit]${NC} $*"; }
err() { echo -e "${RED}[progit]${NC} $*" >&2; exit 1; }

# Parse args
VERSION=""
INSTALL_DIR="${PROGIT_INSTALL_DIR:-}"
FORCE=""

while [ $# -gt 0 ]; do
    case "$1" in
        --version|-v)
            VERSION="$2"
            shift 2
            ;;
        --dir|-d)
            INSTALL_DIR="$2"
            shift 2
            ;;
        --force|-f)
            FORCE="1"
            shift
            ;;
        --help|-h)
            cat << 'EOF'
Usage: install.sh [OPTIONS]

Options:
  --version, -v TAG    Install specific version (e.g. v0.8.0-beta)
  --dir, -d PATH       Install directory (default: ~/.local/bin or /usr/local/bin)
  --force, -f          Overwrite existing installation
  --help, -h           Show this help

Environment:
  PROGIT_HOST          Forgejo host (default: git.sovereign-society.org)
  PROGIT_INSTALL_DIR   Override install directory

Examples:
  curl -fsSL .../install.sh | sh
  curl -fsSL .../install.sh | sh -s -- --version v0.8.0-beta
EOF
            exit 0
            ;;
        *)
            err "Unknown option: $1"
            ;;
    esac
done

# Detect OS
 detect_os() {
    case "$(uname -s)" in
        Linux*)     echo "linux";;
        Darwin*)    echo "darwin";;
        CYGWIN*|MINGW*|MSYS*) echo "windows";;
        *)          echo "unknown";;
    esac
}

# Detect architecture
 detect_arch() {
    case "$(uname -m)" in
        x86_64|amd64) echo "x86_64";;
        aarch64|arm64) echo "aarch64";;
        *)           echo "unknown";;
    esac
}

OS=$(detect_os)
ARCH=$(detect_arch)

if [ "$OS" = "unknown" ] || [ "$ARCH" = "unknown" ]; then
    err "Unsupported platform: ${OS}/${ARCH}. ProGit currently supports linux-x86_64."
fi

# Currently only x86_64-linux is CI-built. Others are best-effort.
if [ "$OS" != "linux" ] || [ "$ARCH" != "x86_64" ]; then
    warn "ProGit releases are currently built for linux-x86_64 only."
    warn "Your platform (${OS}-${ARCH}) may require building from source."
    warn "See: https://${FORGEJO_HOST}/${REPO}#building-from-source"
    exit 1
fi

TARGET="${ARCH}-unknown-${OS}-gnu"

# Fetch release tag
if [ -n "$VERSION" ]; then
    LATEST="$VERSION"
    say "Installing specified version: ${LATEST}"
else
    say "Fetching latest release..."
    LATEST=$(curl -fsSL "${API_URL}/releases/latest" 2>/dev/null | grep -o '"tag_name":"[^"]*"' | head -1 | cut -d'"' -f4 || true)
    if [ -z "$LATEST" ]; then
        warn "No releases found on ${FORGEJO_HOST}."
        warn "The project may not have published releases yet, or the host is unreachable."
        warn ""
        warn "You can:"
        warn "  1. Build from source: git clone https://${FORGEJO_HOST}/${REPO} && cd progit && cargo build --release"
        warn "  2. Install a specific version: curl ... | sh -s -- --version v0.8.0-beta"
        exit 1
    fi
    say "Latest release: ${LATEST}"
fi

VERSION_STR="${LATEST#v}"
STEM="prog-${VERSION_STR}-${TARGET}"
ARCHIVE="${STEM}.tar.gz"
SIG="${ARCHIVE}.minisig"

# Determine install directory
if [ -z "$INSTALL_DIR" ]; then
    if [ -w "/usr/local/bin" ]; then
        INSTALL_DIR="/usr/local/bin"
    elif [ -d "$HOME/.local/bin" ]; then
        INSTALL_DIR="$HOME/.local/bin"
    else
        INSTALL_DIR="$HOME/.local/bin"
        mkdir -p "$INSTALL_DIR"
    fi
fi

# Check if already installed
if [ -f "${INSTALL_DIR}/prog" ] && [ -z "$FORCE" ]; then
    EXISTING=$("${INSTALL_DIR}/prog" --version 2>/dev/null || echo "unknown")
    warn "progit is already installed: ${EXISTING}"
    warn "Use --force to overwrite, or --dir to install elsewhere."
    exit 0
fi

# Check if directory is in PATH
case ":$PATH:" in
    *":$INSTALL_DIR:"*) ;;
    *) warn "$INSTALL_DIR is not in your PATH. Add it to your shell profile.";;
esac

TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT

cd "$TMPDIR"

# Download binary + signature
BASE_URL="https://${FORGEJO_HOST}/${REPO}/releases/download/${LATEST}"
say "Downloading ${ARCHIVE}..."
if ! curl -fsSL "${BASE_URL}/${ARCHIVE}" -o "${ARCHIVE}"; then
    err "Download failed: ${BASE_URL}/${ARCHIVE}"
    err "The release may not exist. Check available releases at:"
    err "  https://${FORGEJO_HOST}/${REPO}/releases"
fi

say "Downloading signature..."
if ! curl -fsSL "${BASE_URL}/${SIG}" -o "${SIG}"; then
    warn "Signature download failed — continuing without verification."
    SIG=""
fi

# Verify signature (if minisign is available and we have a sig)
if [ -n "$SIG" ] && command -v minisign >/dev/null 2>&1; then
    say "Verifying signature..."
    # Fetch public key from repo if not cached
    PUB_KEY="${TMPDIR}/progit-minisign.pub"
    if ! curl -fsSL "https://${FORGEJO_HOST}/${REPO}/raw/branch/main/keys/progit-minisign.pub" -o "$PUB_KEY" 2>/dev/null; then
        warn "Could not fetch public key — signature verification skipped."
    elif minisign -V -p "$PUB_KEY" -m "$ARCHIVE" -x "$SIG" 2>/dev/null; then
        say "Signature verified."
    else
        err "SIGNATURE VERIFICATION FAILED. The downloaded binary may be tampered with."
        err "Aborting installation. Report this to security@sovereign-society.org"
    fi
else
    warn "Signature verification skipped (minisign not installed or no signature)."
    warn "Install minisign for verified downloads: https://jedisct1.github.io/minisign/"
fi

# Extract
say "Extracting..."
tar -xzf "$ARCHIVE"

# Install
say "Installing to ${INSTALL_DIR}..."
if [ -w "$INSTALL_DIR" ]; then
    install -m 755 "prog" "${INSTALL_DIR}/prog"
else
    warn "Need sudo for ${INSTALL_DIR}"
    sudo install -m 755 "prog" "${INSTALL_DIR}/prog"
fi

# Verify installation
if command -v prog >/dev/null 2>&1; then
    INSTALLED_VERSION=$(prog --version 2>/dev/null || echo "unknown")
    say "Installed: ${INSTALLED_VERSION}"
else
    say "Installed to ${INSTALL_DIR}/prog"
    say "Run '${INSTALL_DIR}/prog --version' to verify."
fi

say "Done. Get started: prog --help"
