#!/usr/bin/env bash
set -euo pipefail

export MACOSX_DEPLOYMENT_TARGET="12.0"

cd "$(git rev-parse --show-toplevel)"

PLUGIN_NAME="cagire-plugins"
LIB_NAME="cagire_plugins" # cargo converts hyphens to underscores
OUT="releases"

PLATFORMS=(
    "aarch64-apple-darwin"
    "x86_64-apple-darwin"
    "x86_64-unknown-linux-gnu"
    "aarch64-unknown-linux-gnu"
    "x86_64-pc-windows-gnu"
)

PLATFORM_LABELS=(
    "macOS aarch64 (native)"
    "macOS x86_64 (native)"
    "Linux x86_64 (cross)"
    "Linux aarch64 (cross)"
    "Windows x86_64 (cross)"
)

PLATFORM_ALIASES=(
    "macos-arm64"
    "macos-x86_64"
    "linux-x86_64"
    "linux-aarch64"
    "windows-x86_64"
)

# --- CLI argument parsing ---

cli_platforms=""
cli_targets=""
cli_yes=false
cli_all=false

while [[ $# -gt 0 ]]; do
    case "$1" in
        --platforms) cli_platforms="$2"; shift 2 ;;
        --targets)   cli_targets="$2"; shift 2 ;;
        --yes)       cli_yes=true; shift ;;
        --all)       cli_all=true; shift ;;
        -h|--help)
            echo "Usage: $0 [OPTIONS]"
            echo ""
            echo "Options:"
            echo "  --platforms <list>  Comma-separated: macos-arm64,macos-x86_64,linux-x86_64,linux-aarch64,windows-x86_64"
            echo "  --targets <list>    Comma-separated: cli,desktop,plugins"
            echo "  --all               Build all platforms and targets"
            echo "  --yes               Skip confirmation prompt"
            echo ""
            echo "Without options, runs interactively."
            exit 0
            ;;
        *) echo "Unknown option: $1"; exit 1 ;;
    esac
done

resolve_platform_alias() {
    local alias="$1"
    for i in "${!PLATFORM_ALIASES[@]}"; do
        if [[ "${PLATFORM_ALIASES[$i]}" == "$alias" ]]; then
            echo "$i"
            return
        fi
    done
    echo "Unknown platform: $alias" >&2
    exit 1
}

# --- Helpers ---

prompt_platforms() {
    echo "Select platform (0=all, comma-separated):"
    echo "  0) All"
    for i in "${!PLATFORMS[@]}"; do
        echo "  $((i+1))) ${PLATFORM_LABELS[$i]}"
    done
    read -rp "> " choice

    if [[ "$choice" == "0" || -z "$choice" ]]; then
        selected_platforms=("${PLATFORMS[@]}")
        selected_labels=("${PLATFORM_LABELS[@]}")
    else
        IFS=',' read -ra indices <<< "$choice"
        selected_platforms=()
        selected_labels=()
        for idx in "${indices[@]}"; do
            idx="${idx// /}"
            idx=$((idx - 1))
            if (( idx < 0 || idx >= ${#PLATFORMS[@]} )); then
                echo "Invalid platform index: $((idx+1))"
                exit 1
            fi
            selected_platforms+=("${PLATFORMS[$idx]}")
            selected_labels+=("${PLATFORM_LABELS[$idx]}")
        done
    fi
}

prompt_targets() {
    echo ""
    echo "Select targets (0=all, comma-separated):"
    echo "  0) All"
    echo "  1) cagire"
    echo "  2) cagire-desktop"
    echo "  3) cagire-plugins (CLAP/VST3)"
    read -rp "> " choice

    build_cagire=false
    build_desktop=false
    build_plugins=false

    if [[ "$choice" == "0" || -z "$choice" ]]; then
        build_cagire=true
        build_desktop=true
        build_plugins=true
    else
        IFS=',' read -ra targets <<< "$choice"
        for t in "${targets[@]}"; do
            t="${t// /}"
            case "$t" in
                1) build_cagire=true ;;
                2) build_desktop=true ;;
                3) build_plugins=true ;;
                *) echo "Invalid target: $t"; exit 1 ;;
            esac
        done
    fi
}

confirm_summary() {
    echo ""
    echo "=== Build Summary ==="
    echo ""
    echo "Platforms:"
    for label in "${selected_labels[@]}"; do
        echo "  - $label"
    done
    echo ""
    echo "Targets:"
    $build_cagire  && echo "  - cagire"
    $build_desktop && echo "  - cagire-desktop"
    $build_plugins && echo "  - cagire-plugins (CLAP/VST3)"
    echo ""
    read -rp "Proceed? [Y/n] " yn
    case "${yn,,}" in
        n|no) echo "Aborted."; exit 0 ;;
    esac
}

platform_os() {
    case "$1" in
        *windows*) echo "windows" ;;
        *linux*)   echo "linux" ;;
        *apple*)   echo "macos" ;;
    esac
}

platform_arch() {
    case "$1" in
        aarch64*) echo "aarch64" ;;
        x86_64*)  echo "x86_64" ;;
    esac
}

platform_suffix() {
    case "$1" in
        *windows*) echo ".exe" ;;
        *)         echo "" ;;
    esac
}

is_cross_target() {
    case "$1" in
        *linux*|*windows*) return 0 ;;
        *)                 return 1 ;;
    esac
}

native_target() {
    [[ "$1" == "aarch64-apple-darwin" ]]
}

release_dir() {
    if native_target "$1"; then
        echo "target/release"
    else
        echo "target/$1/release"
    fi
}

target_flag() {
    if native_target "$1"; then
        echo ""
    else
        echo "--target $1"
    fi
}

builder_for() {
    if is_cross_target "$1"; then
        echo "cross"
    else
        echo "cargo"
    fi
}

build_binary() {
    local platform="$1"
    shift
    local builder
    builder=$(builder_for "$platform")
    local tf
    tf=$(target_flag "$platform")
    # shellcheck disable=SC2086
    $builder build --release $tf "$@"
}

bundle_plugins_native() {
    local platform="$1"
    local tf
    tf=$(target_flag "$platform")
    # shellcheck disable=SC2086
    cargo xtask bundle "$PLUGIN_NAME" --release $tf
}

bundle_desktop_native() {
    local platform="$1"
    local tf
    tf=$(target_flag "$platform")
    # shellcheck disable=SC2086
    cargo bundle --release --features desktop --bin cagire-desktop $tf
}

bundle_plugins_cross() {
    local platform="$1"
    local rd
    rd=$(release_dir "$platform")
    local os
    os=$(platform_os "$platform")
    local arch
    arch=$(platform_arch "$platform")

    # Build the cdylib with cross
    # shellcheck disable=SC2046
    build_binary "$platform" -p "$PLUGIN_NAME"

    # Determine source library file
    local src_lib
    case "$os" in
        linux)   src_lib="$rd/lib${LIB_NAME}.so" ;;
        windows) src_lib="$rd/${LIB_NAME}.dll" ;;
    esac

    if [[ ! -f "$src_lib" ]]; then
        echo "    ERROR: Expected library not found: $src_lib"
        return 1
    fi

    # Assemble CLAP bundle (flat file)
    local clap_out="$OUT/${PLUGIN_NAME}-${os}-${arch}.clap"
    cp "$src_lib" "$clap_out"
    echo "    CLAP -> $clap_out"

    # Assemble VST3 bundle (directory tree)
    local vst3_dir="$OUT/${PLUGIN_NAME}-${os}-${arch}.vst3"
    local vst3_contents
    case "$os" in
        linux)
            vst3_contents="$vst3_dir/Contents/${arch}-linux"
            mkdir -p "$vst3_contents"
            cp "$src_lib" "$vst3_contents/${PLUGIN_NAME}.so"
            ;;
        windows)
            vst3_contents="$vst3_dir/Contents/${arch}-win"
            mkdir -p "$vst3_contents"
            cp "$src_lib" "$vst3_contents/${PLUGIN_NAME}.vst3"
            ;;
    esac
    echo "    VST3 -> $vst3_dir/"
}

copy_artifacts() {
    local platform="$1"
    local rd
    rd=$(release_dir "$platform")
    local os
    os=$(platform_os "$platform")
    local arch
    arch=$(platform_arch "$platform")
    local suffix
    suffix=$(platform_suffix "$platform")

    if $build_cagire; then
        local src="$rd/cagire${suffix}"
        local dst="$OUT/cagire-${os}-${arch}${suffix}"
        cp "$src" "$dst"
        echo "    cagire -> $dst"
    fi

    if $build_desktop; then
        local src="$rd/cagire-desktop${suffix}"
        local dst="$OUT/cagire-desktop-${os}-${arch}${suffix}"
        cp "$src" "$dst"
        echo "    cagire-desktop -> $dst"

        # macOS .app bundle
        if [[ "$os" == "macos" ]]; then
            local app_src="$rd/bundle/osx/Cagire.app"
            if [[ ! -d "$app_src" ]]; then
                echo "    ERROR: .app bundle not found at $app_src"
                echo "    Did 'cargo bundle' succeed?"
                return 1
            fi
            local app_dst="$OUT/Cagire-${arch}.app"
            rm -rf "$app_dst"
            cp -R "$app_src" "$app_dst"
            echo "    Cagire.app -> $app_dst"
            scripts/make-dmg.sh "$app_dst" "$OUT"
        fi
    fi

    # MSI installer for Windows targets
    if [[ "$os" == "windows" ]] && command -v cargo-wix &>/dev/null; then
        echo "    Building MSI installer..."
        cargo wix --no-build --nocapture -C -p -C x64
        cp target/wix/*.msi "$OUT/" 2>/dev/null && echo "    MSI -> $OUT/" || true
    fi

    # AppImage for Linux targets
    if [[ "$os" == "linux" ]]; then
        if $build_cagire; then
            scripts/make-appimage.sh "$rd/cagire" "$arch" "$OUT"
        fi
        if $build_desktop; then
            scripts/make-appimage.sh "$rd/cagire-desktop" "$arch" "$OUT"
        fi
    fi

    # Plugin artifacts for native targets (cross handled in bundle_plugins_cross)
    if $build_plugins && ! is_cross_target "$platform"; then
        local bundle_dir="target/bundled"

        # CLAP
        local clap_src="$bundle_dir/${PLUGIN_NAME}.clap"
        if [[ -e "$clap_src" ]]; then
            local clap_dst="$OUT/${PLUGIN_NAME}-${os}-${arch}.clap"
            cp -r "$clap_src" "$clap_dst"
            echo "    CLAP -> $clap_dst"
        fi

        # VST3
        local vst3_src="$bundle_dir/${PLUGIN_NAME}.vst3"
        if [[ -d "$vst3_src" ]]; then
            local vst3_dst="$OUT/${PLUGIN_NAME}-${os}-${arch}.vst3"
            rm -rf "$vst3_dst"
            cp -r "$vst3_src" "$vst3_dst"
            echo "    VST3 -> $vst3_dst/"
        fi
    fi
}

# --- Main ---

if $cli_all; then
    selected_platforms=("${PLATFORMS[@]}")
    selected_labels=("${PLATFORM_LABELS[@]}")
    build_cagire=true
    build_desktop=true
    build_plugins=true
elif [[ -n "$cli_platforms" || -n "$cli_targets" ]]; then
    # Resolve platforms from CLI
    if [[ -n "$cli_platforms" ]]; then
        selected_platforms=()
        selected_labels=()
        IFS=',' read -ra aliases <<< "$cli_platforms"
        for alias in "${aliases[@]}"; do
            alias="${alias// /}"
            idx=$(resolve_platform_alias "$alias")
            selected_platforms+=("${PLATFORMS[$idx]}")
            selected_labels+=("${PLATFORM_LABELS[$idx]}")
        done
    else
        selected_platforms=("${PLATFORMS[@]}")
        selected_labels=("${PLATFORM_LABELS[@]}")
    fi

    # Resolve targets from CLI
    build_cagire=false
    build_desktop=false
    build_plugins=false
    if [[ -n "$cli_targets" ]]; then
        IFS=',' read -ra tgts <<< "$cli_targets"
        for t in "${tgts[@]}"; do
            t="${t// /}"
            case "$t" in
                cli)     build_cagire=true ;;
                desktop) build_desktop=true ;;
                plugins) build_plugins=true ;;
                *) echo "Unknown target: $t (expected: cli, desktop, plugins)"; exit 1 ;;
            esac
        done
    else
        build_cagire=true
        build_desktop=true
        build_plugins=true
    fi
else
    prompt_platforms
    prompt_targets
fi

if ! $cli_yes && [[ -z "$cli_platforms" ]] && ! $cli_all; then
    confirm_summary
fi

mkdir -p "$OUT"

step=0
total=${#selected_platforms[@]}

for platform in "${selected_platforms[@]}"; do
    step=$((step + 1))
    echo ""
    echo "=== [$step/$total] $platform ==="

    if $build_cagire; then
        echo "  -> cagire"
        build_binary "$platform"
    fi

    if $build_desktop; then
        echo "  -> cagire-desktop"
        build_binary "$platform" --features desktop --bin cagire-desktop
        if ! is_cross_target "$platform"; then
            echo "  -> bundling cagire-desktop .app"
            bundle_desktop_native "$platform"
        fi
    fi

    if $build_plugins; then
        echo "  -> cagire-plugins"
        if is_cross_target "$platform"; then
            bundle_plugins_cross "$platform"
        else
            bundle_plugins_native "$platform"
        fi
    fi

    echo "  Copying artifacts..."
    copy_artifacts "$platform"
done

echo ""
echo "=== Done ==="
echo ""
ls -lhR "$OUT/"
