#!/usr/bin/env bash
#
# build-libs.sh — build libvoicecat for each supported client platform and
# stage the artifacts under dist/lib/.
#
# Artifacts per platform:
#   macos       → dist/lib/macos/        libvoicecat.a + libvoicecat-fat.a + voicecat.h + module.modulemap
#   ios         → dist/lib/ios-device/   (arm64-ios slice)
#   ios-sim     → dist/lib/ios-sim/      (arm64-ios-sim slice)
#   windows     → dist/lib/windows/      voicecat.dll + voicecat.h
#   xcframework → dist/lib/VoiceCatCore.xcframework/   (stitched Apple slices)
#
# The Apple slices + XCFramework are produced by clients/apple/scripts/
# build-xcframework.sh (the validated flow); this script drives it and stages
# the outputs. The Windows DLL comes from the `windows-client` preset.
#
# Usage:
#   scripts/build-libs.sh                       # host default (macos on macOS, windows on Windows)
#   scripts/build-libs.sh --platform macos
#   scripts/build-libs.sh --platform ios
#   scripts/build-libs.sh --platform ios-sim
#   scripts/build-libs.sh --platform windows
#   scripts/build-libs.sh --all-apple           # macos + ios + ios-sim + xcframework (macOS host)
#   scripts/build-libs.sh --all                 # everything buildable on this host
#   scripts/build-libs.sh --dist /out --no-configure
#   scripts/build-libs.sh -h|--help
#
# Platform availability: macos / ios / ios-sim require a macOS host; windows
# requires a Windows host. Requires VCPKG_ROOT.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VC_SCRIPT_NAME="build-libs"
source "$SCRIPT_DIR/common.sh"

PLATFORMS=()
DO_CONFIGURE=true
while [[ $# -gt 0 ]]; do
    case "$1" in
        --dist)         vc_set_dist "$2"; shift 2 ;;
        --no-configure) DO_CONFIGURE=false; shift ;;
        --platform)     PLATFORMS+=( "$2" ); shift 2 ;;
        --all-apple)    PLATFORMs_all_apple=1; shift ;;
        --all)          PLATFORMS=( all-host ); shift ;;
        -h|--help)      vc_print_help "$0"; exit 0 ;;
        *) vc_die "unknown arg: $1 (try --help)" ;;
    esac
done

HOST="$(vc_host_os)"

# --all-apple expands to the three Apple platforms.
if [[ -n "${PLATFORMs_all_apple:-}" ]]; then
    PLATFORMS=( macos ios ios-sim )
fi

# Default: host-appropriate single platform.
if [[ ${#PLATFORMS[@]} -eq 0 ]]; then
    case "$HOST" in
        macos)   PLATFORMS=( macos ) ;;
        windows) PLATFORMS=( windows ) ;;
        *) vc_die "no default library platform for host '$HOST'. Pass --platform explicitly." ;;
    esac
fi

# Expand the meta-target.
if [[ " ${PLATFORMS[*]} " == *" all-host "* ]]; then
    PLATFORMS=()
    case "$HOST" in
        macos)   PLATFORMS=( macos ios ios-sim ) ;;
        windows) PLATFORMS=( windows ) ;;
        *) vc_die "--all: nothing buildable on host '$HOST'." ;;
    esac
fi

vc_log "dist dir: $VC_DIST_DIR"
vc_log "platforms: ${PLATFORMS[*]}"

# Validate platform availability against host.
for p in "${PLATFORMS[@]}"; do
    case "$p" in
        macos|ios|ios-sim) [[ "$HOST" == "macos" ]]   || vc_die "platform '$p' requires a macOS host." ;;
        windows)           [[ "$HOST" == "windows" ]] || vc_die "platform '$p' requires a Windows host." ;;
        *) vc_die "unknown platform '$p' (try --help)" ;;
    esac
done

HAVE_APPLE=false
HAVE_WINDOWS=false
for p in "${PLATFORMS[@]}"; do
    case "$p" in
        macos|ios|ios-sim) HAVE_APPLE=true ;;
        windows)           HAVE_WINDOWS=true ;;
    esac
done

# ── Apple slices + XCFramework ──────────────────────────────────────────────────
# Stage one slice's .a + headers + module map into dist/lib/<sub>.
stage_apple_slice() {
    local preset="$1" sub="$2"
    local lib="$VC_REPO_ROOT/build/$preset/lib/libvoicecat.a"
    local fat="$VC_REPO_ROOT/build/$preset/lib/libvoicecat-fat.a"
    local out; out="$(vc_dist_subdir "lib/$sub")"
    [[ -f "$lib" ]] || vc_die "expected $lib not found (did the xcframework build run?)"
    cp "$lib" "$out/"
    [[ -f "$fat" ]] && cp "$fat" "$out/" || true
    cp "$VC_REPO_ROOT/core/include/voicecat.h" "$out/"
    cat > "$out/module.modulemap" <<'MM'
module VoiceCatC {
    header "voicecat.h"
    export *
}
MM
    vc_ok "$sub: libvoicecat.a ($(vc_file_size "$lib") bytes) -> $out"
}

if $HAVE_APPLE; then
    vc_resolve_vcpkg_root apple-dev
    vc_step "build Apple slices via build-xcframework.sh"

    ALL_THREE=false
    if [[ " ${PLATFORMS[*]} " == *" macos "* && " ${PLATFORMS[*]} " == *" ios "* && " ${PLATFORMS[*]} " == *" ios-sim "* ]]; then
        ALL_THREE=true
    fi

    xcfw_invoke() {
        local args=()
        $DO_CONFIGURE || args+=( --no-configure )
        args+=( "$@" )
        "$VC_REPO_ROOT/clients/apple/scripts/build-xcframework.sh" "${args[@]}"
    }

    if $ALL_THREE; then
        xcfw_invoke --all
        stage_apple_slice apple-dev       macos
        stage_apple_slice apple-ios       ios-device
        stage_apple_slice apple-ios-sim   ios-sim
    else
        for p in "${PLATFORMS[@]}"; do
            case "$p" in
                macos)   xcfw_invoke --preset apple-dev;     stage_apple_slice apple-dev     macos ;;
                ios)     xcfw_invoke --preset apple-ios;     stage_apple_slice apple-ios     ios-device ;;
                ios-sim) xcfw_invoke --preset apple-ios-sim; stage_apple_slice apple-ios-sim ios-sim ;;
            esac
        done
    fi

    # Stage the stitched XCFramework (whatever slices the last call produced).
    XCFW="$VC_REPO_ROOT/clients/apple/VoiceCatCore.xcframework"
    [[ -d "$XCFW" ]] || vc_die "xcframework not found at $XCFW"
    LIB_DIR="$VC_DIST_DIR/lib"
    mkdir -p "$LIB_DIR"
    rm -rf "$LIB_DIR/VoiceCatCore.xcframework"
    cp -R "$XCFW" "$LIB_DIR/"
    vc_ok "VoiceCatCore.xcframework -> $LIB_DIR/"
fi

# ── Windows DLL ─────────────────────────────────────────────────────────────────
if $HAVE_WINDOWS; then
    vc_resolve_vcpkg_root windows-client
    vc_step "build Windows DLL (preset: windows-client)"
    if $DO_CONFIGURE; then
        cmake --preset windows-client
    fi
    cmake --build --preset windows-client
    DLL="$VC_REPO_ROOT/build/windows-client/bin/voicecat.dll"
    [[ -f "$DLL" ]] || vc_die "expected $DLL not found"
    OUT="$(vc_dist_subdir lib/windows)"
    cp "$DLL" "$OUT/"
    cp "$VC_REPO_ROOT/core/include/voicecat.h" "$OUT/"
    vc_ok "windows: voicecat.dll ($(vc_file_size "$DLL") bytes) -> $OUT"
fi

vc_ok "done -> $VC_DIST_DIR/lib"
