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

# macOS Production Build Script for the SDL3 Spacetris project
# Mirrors the Windows PowerShell workflow but uses common POSIX tooling so it
# can be executed on macOS runners or local developer machines.

PROJECT_NAME="spacetris"
BUILD_DIR="build-release"
OUTPUT_DIR="dist"
PACKAGE_DIR=""
VERSION="$(date +"%Y.%m.%d")"
CLEAN=0
PACKAGE_ONLY=0
PACKAGE_RUNTIME_DIR=""
APP_ICON_SRC="assets/favicon/favicon-512x512.png"
APP_ICON_ICNS="assets/favicon/AppIcon.icns"

print_usage() {
    cat <<'USAGE'
Usage: ./build-production-mac.sh [options]

Options:
  -c, --clean          Remove existing build + dist folders before running
  -p, --package-only   Skip compilation and only rebuild the distributable
  -o, --output DIR     Customize output directory (default: dist)
  -h, --help           Show this help text
USAGE
}

log() {
    local level=$1; shift
    case "$level" in
        INFO) printf '\033[36m[INFO]\033[0m %s\n' "$*" ;;
        OK) printf '\033[32m[ OK ]\033[0m %s\n' "$*" ;;
        WARN) printf '\033[33m[WARN]\033[0m %s\n' "$*" ;;
        ERR) printf '\033[31m[ERR ]\033[0m %s\n' "$*" ;;
        *) printf '%s\n' "$*" ;;
    esac
}

require_macos() {
    if [[ $(uname) != "Darwin" ]]; then
        log ERR "This script is intended for macOS hosts."
        exit 1
    fi
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -c|--clean) CLEAN=1; shift ;;
            -p|--package-only) PACKAGE_ONLY=1; shift ;;
            -o|--output)
                if [[ $# -lt 2 ]]; then
                    log ERR "--output requires a directory argument"
                    exit 1
                fi
                OUTPUT_DIR="$2"; shift 2 ;;
            -h|--help) print_usage; exit 0 ;;
            *)
                log ERR "Unknown argument: $1"
                print_usage
                exit 1 ;;
        esac
    done
}

configure_paths() {
    PACKAGE_DIR="${OUTPUT_DIR}/SpacetrisGame-mac"
}

generate_icns_if_needed() {
    if [[ -f "$APP_ICON_ICNS" ]]; then
        return
    fi
    if [[ ! -f "$APP_ICON_SRC" ]]; then
        log WARN "Icon source PNG not found ($APP_ICON_SRC); skipping .icns generation"
        return
    fi
    if ! command -v iconutil >/dev/null 2>&1; then
        log WARN "iconutil not available; skipping .icns generation"
        return
    fi
    log INFO "Generating AppIcon.icns from $APP_ICON_SRC ..."
    tmpdir=$(mktemp -d)
    iconset="$tmpdir/AppIcon.iconset"
    mkdir -p "$iconset"
    # Generate required sizes from 512 base; sips will downscale
    for size in 16 32 64 128 256 512; do
        sips -s format png "$APP_ICON_SRC" --resampleHeightWidth $size $size --out "$iconset/icon_${size}x${size}.png" >/dev/null
        sips -s format png "$APP_ICON_SRC" --resampleHeightWidth $((size*2)) $((size*2)) --out "$iconset/icon_${size}x${size}@2x.png" >/dev/null
    done
    iconutil -c icns "$iconset" -o "$APP_ICON_ICNS" || log WARN "iconutil failed to create .icns"
    rm -rf "$tmpdir"
    if [[ -f "$APP_ICON_ICNS" ]]; then
        log OK "Created $APP_ICON_ICNS"
    fi
}

clean_previous() {
    if (( CLEAN )); then
        log INFO "Cleaning previous build artifacts..."
        rm -rf "$BUILD_DIR" "$OUTPUT_DIR"
        log OK "Previous artifacts removed"
    fi
}

configure_and_build() {
    if (( PACKAGE_ONLY )); then
        return
    fi

    log INFO "Configuring CMake (Release)..."
    cmake -S . -B "$BUILD_DIR" -DCMAKE_BUILD_TYPE=Release
    log OK "CMake configure complete"

    log INFO "Building Release target..."
    cmake --build "$BUILD_DIR" --config Release
    log OK "Build finished"
}

resolve_executable() {
    local candidates=(
        "$BUILD_DIR/Release/${PROJECT_NAME}"
        "$BUILD_DIR/${PROJECT_NAME}"
        "$BUILD_DIR/${PROJECT_NAME}.app/Contents/MacOS/${PROJECT_NAME}"
    )

    for path in "${candidates[@]}"; do
        if [[ -x "$path" ]]; then
            EXECUTABLE_PATH="$path"
            break
        fi
    done

    if [[ -z ${EXECUTABLE_PATH:-} ]]; then
        log ERR "Unable to locate built executable."
        exit 1
    fi

    if [[ "$EXECUTABLE_PATH" == *.app/Contents/MacOS/* ]]; then
        APP_BUNDLE_PATH="${EXECUTABLE_PATH%/Contents/MacOS/*}"
    else
        APP_BUNDLE_PATH=""
    fi

    log OK "Using executable: $EXECUTABLE_PATH"
}

prepare_package_dir() {
    log INFO "Creating package directory $PACKAGE_DIR ..."
    rm -rf "$PACKAGE_DIR"
    mkdir -p "$PACKAGE_DIR"
}

copy_binary_or_bundle() {
    if [[ -n ${APP_BUNDLE_PATH:-} ]]; then
        log INFO "Copying app bundle..."
        rsync -a "$APP_BUNDLE_PATH" "$PACKAGE_DIR/"
        local app_name="${APP_BUNDLE_PATH##*/}"
        PACKAGE_BINARY="${app_name}/Contents/MacOS/${PROJECT_NAME}"
        PACKAGE_RUNTIME_DIR="$PACKAGE_DIR/${app_name}/Contents/MacOS"
    else
        log INFO "Copying executable..."
        cp "$EXECUTABLE_PATH" "$PACKAGE_DIR/${PROJECT_NAME}"
        chmod +x "$PACKAGE_DIR/${PROJECT_NAME}"
        PACKAGE_BINARY="${PROJECT_NAME}"
        PACKAGE_RUNTIME_DIR="$PACKAGE_DIR"
    fi
    log OK "Binary ready (${PACKAGE_BINARY})"
}

copy_assets() {
    if [[ -n ${APP_BUNDLE_PATH:-} ]]; then
        log INFO "Assets already bundled inside the .app; skipping external copy."
        return
    fi
    log INFO "Copying assets..."
    local folders=("assets" "fonts")
    for folder in "${folders[@]}"; do
        if [[ -d "$folder" ]]; then
            rsync -a "$folder" "$PACKAGE_DIR/"
            log OK "Copied $folder"
        fi
    done
    if [[ -f "FreeSans.ttf" ]]; then
        cp "FreeSans.ttf" "$PACKAGE_DIR/"
        log OK "Copied FreeSans.ttf"
    fi
}

copy_dependencies() {
    log INFO "Collecting dynamic libraries from vcpkg..."
    local triplets=("arm64-osx" "x64-osx" "universal-osx")
    local bases=("$BUILD_DIR/vcpkg_installed" "vcpkg_installed")
    local copied_names=()

    for base in "${bases[@]}"; do
        for triplet in "${triplets[@]}"; do
            for sub in lib bin; do
                local dir="$base/$triplet/$sub"
                if [[ -d "$dir" ]]; then
                    while IFS= read -r -d '' dylib; do
                        local name=$(basename "$dylib")
                        local seen=0
                        for existing in "${copied_names[@]}"; do
                            if [[ "$existing" == "$name" ]]; then
                                seen=1
                                break
                            fi
                        done
                        if (( !seen )); then
                            cp "$dylib" "$PACKAGE_RUNTIME_DIR/"
                            copied_names+=("$name")
                            log OK "Copied $name"
                        fi
                    done < <(find "$dir" -maxdepth 1 -type f -name '*.dylib' -print0)
                fi
            done
        done
    done

    if [[ ${#copied_names[@]} -eq 0 ]]; then
        log WARN "No .dylib files found; ensure vcpkg installed macOS triplet dependencies."
    fi
}

ensure_rpath() {
    local binary="$PACKAGE_DIR/$PACKAGE_BINARY"
    if [[ ! -f "$binary" ]]; then
        return
    fi
    if command -v otool >/dev/null 2>&1 && command -v install_name_tool >/dev/null 2>&1; then
        if ! otool -l "$binary" | grep -A2 LC_RPATH | grep -q '@executable_path'; then
            log INFO "Adding @executable_path rpath"
            install_name_tool -add_rpath "@executable_path" "$binary"
        fi
    fi
}

create_launchers() {
    local launch_command="./${PROJECT_NAME}"
    if [[ "$PACKAGE_BINARY" == *.app/Contents/MacOS/* ]]; then
        local app_dir="${PACKAGE_BINARY%%/Contents/*}"
        launch_command="open \"./${app_dir}\""
    fi

        cat > "$PACKAGE_DIR/Launch-Spacetris.command" <<EOF
    #!/usr/bin/env bash
    cd "\$(dirname \"\$0\")"
    ${launch_command}
    EOF
    chmod +x "$PACKAGE_DIR/Launch-Spacetris.command"

    cat > "$PACKAGE_DIR/README-mac.txt" <<EOF
Spacetris SDL3 Game - macOS Release $VERSION
=========================================

Requirements:
- macOS 12 Monterey or newer (Apple Silicon or Intel)
- GPU with Metal support

Installation:
1. Unzip the archive anywhere (e.g., ~/Games/Spacetris).
2. Ensure the executable bit stays set (script already does this).
3. Double-click Launch-Spacetris.command or run the binary/app manually from Terminal or Finder.

Files:
- spacetris / Launch-Spacetris.command (start the game)
- assets/ (art, audio, fonts)
- *.dylib from SDL3 and related dependencies
- FreeSans.ttf font

Enjoy!
EOF
    log OK "Created README and launcher"
}

validate_package() {
    log INFO "Validating package contents..."
    local missing=()
    local required=("$PACKAGE_BINARY")
    if [[ -z ${APP_BUNDLE_PATH:-} ]]; then
        required+=(assets FreeSans.ttf)
    fi
    for required in "${required[@]}"; do
        if [[ ! -e "$PACKAGE_DIR/$required" ]]; then
            missing+=("$required")
        fi
    done
    if (( ${#missing[@]} > 0 )); then
        log WARN "Missing: ${missing[*]}"
    else
        log OK "Package looks complete"
    fi
}

create_zip() {
    mkdir -p "$OUTPUT_DIR"
    local zip_name="SpacetrisGame-mac-${VERSION}.zip"
    local zip_path="$OUTPUT_DIR/$zip_name"
    log INFO "Creating zip archive $zip_path ..."
    if command -v ditto >/dev/null 2>&1; then
        ditto -c -k --keepParent "$PACKAGE_DIR" "$zip_path"
    else
        (cd "$OUTPUT_DIR" && zip -r "$zip_name" "$(basename "$PACKAGE_DIR")")
    fi
    log OK "Zip created"
}

main() {
    parse_args "$@"
    require_macos
    configure_paths

    if [[ ! -f "CMakeLists.txt" ]]; then
        log ERR "Run from repository root (CMakeLists.txt missing)."
        exit 1
    fi

    log INFO "======================================"
    log INFO "   macOS Production Builder"
    log INFO "======================================"
    log INFO "Version: $VERSION"
    log INFO "Output:  $OUTPUT_DIR"

    clean_previous
    generate_icns_if_needed
    configure_and_build
    resolve_executable
    prepare_package_dir
    copy_binary_or_bundle
    copy_assets
    copy_dependencies
    ensure_rpath
    create_launchers
    validate_package
    create_zip
    create_dmg

    log INFO "Done. Package available at $PACKAGE_DIR"
}

create_dmg() {
    if [[ -z ${APP_BUNDLE_PATH:-} ]]; then
        log INFO "No app bundle detected; skipping DMG creation"
        return
    fi
    
    local app_name="${APP_BUNDLE_PATH##*/}"
    local dmg_name="SpacetrisGame-mac-${VERSION}.dmg"
    local dmg_path="$OUTPUT_DIR/$dmg_name"
    
    if [[ ! -f "scripts/create-dmg.sh" ]]; then
        log WARN "scripts/create-dmg.sh not found; skipping DMG creation"
        return
    fi
    
    log INFO "Creating DMG installer: $dmg_path"
    bash scripts/create-dmg.sh "$PACKAGE_DIR/$app_name" "$dmg_path" || log WARN "DMG creation failed"
    
    if [[ -f "$dmg_path" ]]; then
        log OK "DMG created: $dmg_path"
    fi
}

main "$@"
