# GitLab CI/CD Pipeline for MPV.Rocks Installer
# Builds installers for all platforms, runs tests,
# generates BLAKE3 checksums, and creates releases
#
# Runner: 20 EPYC 7742 cores, 24GB RAM
# Optimized for parallel execution with aggressive caching

# Define default variables
variables:
  BINARY_NAME: "mpv-manager"
  GENERATOR_NAME: "generate-info"
  CHECKSUMS_NAME: "gen-checksums"
  VERSION: "${CI_COMMIT_TAG:-1.0.0-dev}"
  GO_VERSION: "1.26"
  BUILD_TIME: "${CI_PIPELINE_CREATED_AT}"
  GIT_COMMIT: "${CI_COMMIT_SHORT_SHA}"
  # Enable Go compiler parallelism (use 4 cores per job)
  GOMAXPROCS: "4"
  # Use faster linker
  CGO_ENABLED: "0"
  # Disable cgo for all builds
  GOPROXY: "https://proxy.golang.org,direct"
  # Enable Go module and build caching
  GOCACHE: "${CI_PROJECT_DIR}/.cache/go-build"
  GOMODCACHE: "${CI_PROJECT_DIR}/.cache/go-mod"

# Global cache configuration for Go modules and build cache
cache:
  key: "${CI_JOB_NAME}"
  paths:
    - .cache/go-build/
    - .cache/go-mod/

# Define stages
stages:
  - test
  - build
  - checksum
  - release

# ============================================================================
# TEST STAGE - Runs on all pushes to master
# ============================================================================

test:linux:
  stage: test
  image: golang:${GO_VERSION}
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_TAG
  before_script:
    - apt-get update -qq && apt-get install -y -qq git gcc
    - git config --global --add safe.directory ${CI_PROJECT_DIR}
    - mkdir -p .cache/go-build .cache/go-mod
  script:
    # Download modules (cached between runs)
    - go mod download
    - go mod tidy
    # Run tests with parallelism (4 packages in parallel, tests run with race detector)
    - go test -v -race -p 4 -timeout 5m ./...
    # Run coverage separately (faster without race detector)
    - go test -cover -p 4 ./...
  coverage: '/coverage: \d+\.\d+% of statements/'
  # Race detector requires CGO
  variables:
    CGO_ENABLED: "1"
    GOMAXPROCS: "8"
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
  tags:
    - docker

# ============================================================================
# BUILD STAGE - Installer Binaries (only on tags)
# ============================================================================

# Template for build jobs (DRY - defines common settings)
.build_template: &build_template
  image: golang:${GO_VERSION}
  rules:
    - if: $CI_COMMIT_TAG
  before_script:
    - mkdir -p dist .cache/go-build .cache/go-mod
    - go mod download
  script:
    - |
      CGO_ENABLED=0 go build -buildvcs=false \
        -p 4 \
        -ldflags "-X gitgud.io/mike/mpv-manager/pkg/version.CurrentVersion=${VERSION} \
        -X gitgud.io/mike/mpv-manager/pkg/version.BuildTime=${BUILD_TIME} \
        -X gitgud.io/mike/mpv-manager/pkg/version.GitCommit=${GIT_COMMIT} \
        -s -w" \
        -o ${OUTPUT_PATH} \
        ./cmd/mpv-manager
  artifacts:
    paths:
      - ${OUTPUT_PATH}
    expire_in: 1 day
  tags:
    - docker

# Linux Builds
build:linux-amd64:
  stage: build
  <<: *build_template
  variables:
    GOOS: linux
    GOARCH: amd64
    GOAMD64: v2
    OUTPUT_PATH: dist/${BINARY_NAME}-linux-amd64

build:linux-arm64:
  stage: build
  <<: *build_template
  variables:
    GOOS: linux
    GOARCH: arm64
    OUTPUT_PATH: dist/${BINARY_NAME}-linux-arm64

# Windows Builds
build:windows-x86_64:
  stage: build
  <<: *build_template
  variables:
    GOOS: windows
    GOARCH: amd64
    GOAMD64: v2
    OUTPUT_PATH: dist/${BINARY_NAME}-win-x86_64.exe

build:windows-arm64:
  stage: build
  <<: *build_template
  variables:
    GOOS: windows
    GOARCH: arm64
    OUTPUT_PATH: dist/${BINARY_NAME}-win-arm64.exe

# macOS Builds
build:macos-intel:
  stage: build
  <<: *build_template
  variables:
    GOOS: darwin
    GOARCH: amd64
    GOAMD64: v2
    OUTPUT_PATH: dist/${BINARY_NAME}-macos-intel

build:macos-arm:
  stage: build
  <<: *build_template
  variables:
    GOOS: darwin
    GOARCH: arm64
    OUTPUT_PATH: dist/${BINARY_NAME}-macos-arm

# ============================================================================
# BUILD STAGE - Internal Tools (for CI only, not released)
# ============================================================================

# Template for internal tool builds
.tool_template: &tool_template
  image: golang:${GO_VERSION}
  rules:
    - if: $CI_COMMIT_TAG
  before_script:
    - mkdir -p dist .cache/go-build .cache/go-mod
    - go mod download
  script:
    - |
      CGO_ENABLED=0 go build -buildvcs=false \
        -p 4 \
        -ldflags "-X gitgud.io/mike/mpv-manager/pkg/version.CurrentVersion=${VERSION} \
        -X gitgud.io/mike/mpv-manager/pkg/version.BuildTime=${BUILD_TIME} \
        -X gitgud.io/mike/mpv-manager/pkg/version.GitCommit=${GIT_COMMIT} \
        -s -w" \
        -o ${OUTPUT_PATH} \
        ${SOURCE_PATH}
  artifacts:
    paths:
      - ${OUTPUT_PATH}
    expire_in: 1 day
  tags:
    - docker

# Generator tool (Linux AMD64 only - for generating releases.json)
build:generator:
  stage: build
  <<: *tool_template
  variables:
    OUTPUT_PATH: dist/${GENERATOR_NAME}
    SOURCE_PATH: ./cmd/generate-info

# Checksums tool (Linux AMD64 only - for generating BLAKE3 checksums)
build:checksums:
  stage: build
  <<: *tool_template
  variables:
    OUTPUT_PATH: dist/${CHECKSUMS_NAME}
    SOURCE_PATH: ./cmd/gen-checksums

# ============================================================================
# PACKAGE STAGE - Create Release Packages (only on tags)
# ============================================================================

package:linux:
  stage: checksum
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - build:linux-amd64
    - build:linux-arm64
  script:
    - cd dist
    - tar -czf ${BINARY_NAME}-${CI_COMMIT_TAG}-linux-amd64.tar.gz ${BINARY_NAME}-linux-amd64
    - tar -czf ${BINARY_NAME}-${CI_COMMIT_TAG}-linux-arm64.tar.gz ${BINARY_NAME}-linux-arm64
    - ls -lh
  artifacts:
    paths:
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-linux-amd64.tar.gz
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-linux-arm64.tar.gz
    expire_in: 1 day
  tags:
    - docker

package:windows:
  stage: checksum
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - build:windows-x86_64
    - build:windows-arm64
  script:
    - apk add --no-cache zip
    - cd dist
    - zip -q ${BINARY_NAME}-${CI_COMMIT_TAG}-win-x86_64.zip ${BINARY_NAME}-win-x86_64.exe
    - zip -q ${BINARY_NAME}-${CI_COMMIT_TAG}-win-arm64.zip ${BINARY_NAME}-win-arm64.exe
    - ls -lh
  artifacts:
    paths:
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-win-x86_64.zip
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-win-arm64.zip
    expire_in: 1 day
  tags:
    - docker

package:macos:
  stage: checksum
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - build:macos-intel
    - build:macos-arm
  script:
    - apk add --no-cache zip
    - cd dist
    - zip -q ${BINARY_NAME}-${CI_COMMIT_TAG}-macos-intel.zip ${BINARY_NAME}-macos-intel
    - zip -q ${BINARY_NAME}-${CI_COMMIT_TAG}-macos-arm.zip ${BINARY_NAME}-macos-arm
    - ls -lh
  artifacts:
    paths:
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-macos-intel.zip
      - dist/${BINARY_NAME}-${CI_COMMIT_TAG}-macos-arm.zip
    expire_in: 1 day
  tags:
    - docker

# ============================================================================
# CHECKSUM STAGE - Generate BLAKE3 Checksums (only on tags)
# ============================================================================

checksums:
  stage: checksum
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - package:linux
    - package:windows
    - package:macos
    - build:checksums
  script:
    - apk add --no-cache tar zip
    - cd dist
    - echo "Generating BLAKE3 checksums..."
    - ./${CHECKSUMS_NAME} .
    - cat BLAKE3SUMS.txt
  artifacts:
    paths:
      - dist/BLAKE3SUMS.txt
    expire_in: 1 day
  tags:
    - docker

# ============================================================================
# PACKAGE REGISTRY STAGE - Publish to GitLab Generic Package Registry
# This provides reliable direct-download URLs for the self-updater
# URL format: https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/v0.8.0/mpv-manager-linux-amd64
# ============================================================================

publish:package-registry:
  stage: release
  image: alpine:latest
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - build:linux-amd64
    - build:linux-arm64
    - build:windows-x86_64
    - build:windows-arm64
    - build:macos-intel
    - build:macos-arm
    - package:linux
    - package:windows
    - package:macos
    - checksums
  before_script:
    - apk add --no-cache curl parallel
  script:
    - echo "Listing dist/ contents..."
    - ls -la dist/
    - echo "Uploading binaries to package registry..."
    # Upload all files in parallel using GNU parallel (max 4 concurrent uploads)
    # Use -f to fail on HTTP errors, --retry for transient failures, --halt to stop on failure
    - |
      cd dist && parallel -j 4 --halt soon,fail=1 \
        'curl -sf --retry 3 --retry-delay 2 --header "JOB-TOKEN: $CI_JOB_TOKEN" \
          --upload-file {} \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/{}" && \
          echo "✓ Uploaded {}"' \
        ::: mpv-manager-linux-amd64 mpv-manager-linux-arm64 \
            mpv-manager-win-x86_64.exe mpv-manager-win-arm64.exe \
            mpv-manager-macos-intel mpv-manager-macos-arm \
            mpv-manager-${CI_COMMIT_TAG}-linux-amd64.tar.gz \
            mpv-manager-${CI_COMMIT_TAG}-linux-arm64.tar.gz \
            mpv-manager-${CI_COMMIT_TAG}-win-x86_64.zip \
            mpv-manager-${CI_COMMIT_TAG}-win-arm64.zip \
            mpv-manager-${CI_COMMIT_TAG}-macos-intel.zip \
            mpv-manager-${CI_COMMIT_TAG}-macos-arm.zip \
            BLAKE3SUMS.txt
    - echo "All uploads complete!"
  tags:
    - docker

# ============================================================================
# RELEASE STAGE - Create GitLab Release (only on tags)
# ============================================================================

release:
  stage: release
  image: registry.gitlab.com/gitlab-org/release-cli:latest
  needs:
    - publish:package-registry
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - echo "Creating GitLab release for ${CI_COMMIT_TAG}"
  release:
    tag_name: $CI_COMMIT_TAG
    name: "MPV.Rocks Manager ${CI_COMMIT_TAG}"
    description: |
      MPV.Rocks Manager ${CI_COMMIT_TAG}

      ## Installation

      Download the archive for your platform, extract it, and run the binary.

      ### 🪟 Windows (Intel/AMD)
      (If you're unsure, you probably want this one)
      [Download mpv-manager-${CI_COMMIT_TAG}-win-x86_64.zip](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-win-x86_64.zip)

      Extract the zip file and double-click `mpv-manager-win-x86_64.exe`

      ### 🪟 Windows (ARM)
      [Download mpv-manager-${CI_COMMIT_TAG}-win-arm64.zip](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-win-arm64.zip)

      Extract the zip file and double-click `mpv-manager-win-arm64.exe`

      ### 🍎 macOS (Intel)
      [Download mpv-manager-${CI_COMMIT_TAG}-macos-intel.zip](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-macos-intel.zip)
      ```bash
      unzip mpv-manager-${CI_COMMIT_TAG}-macos-intel.zip
      ./mpv-manager-macos-intel
      ```

      ### 🍎 macOS (Apple Silicon)
      [Download mpv-manager-${CI_COMMIT_TAG}-macos-arm.zip](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-macos-arm.zip)
      ```bash
      unzip mpv-manager-${CI_COMMIT_TAG}-macos-arm.zip
      ./mpv-manager-macos-arm
      ```

      ### 🐧 Linux (Intel/AMD)
      [Download mpv-manager-${CI_COMMIT_TAG}-linux-amd64.tar.gz](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-linux-amd64.tar.gz)
      ```bash
      tar -xzf mpv-manager-${CI_COMMIT_TAG}-linux-amd64.tar.gz
      ./mpv-manager-linux-amd64
      ```

      ### 🐧 Linux (ARM)
      [Download mpv-manager-${CI_COMMIT_TAG}-linux-arm64.tar.gz](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-linux-arm64.tar.gz)
      ```bash
      tar -xzf mpv-manager-${CI_COMMIT_TAG}-linux-arm64.tar.gz
      ./mpv-manager-linux-arm64
      ```

      ## Verification

      Download [BLAKE3SUMS.txt](https://gitgud.io/api/v4/projects/mike%2Fmpv-manager/packages/generic/mpv-manager/${CI_COMMIT_TAG}/BLAKE3SUMS.txt) and verify with b3sum:
      ```bash
      # Install b3sum (choose one):
      # macOS:     brew install b3sum
      # Debian:    sudo apt install b3sum
      # Fedora:    sudo dnf install b3sum
      # Arch:      sudo pacman -S b3sum
      # OpenSUSE:  sudo zypper install b3sum
      # Rust:      cargo install b3sum

      # Verify the download
      b3sum -c BLAKE3SUMS.txt
      ```
    assets:
      links:
        # Archives (for user downloads) - Windows first
        - name: "🪟 Windows (Intel/AMD)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-win-x86_64.zip"
        - name: "🪟 Windows (ARM)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-win-arm64.zip"
        - name: "🍎 macOS (Intel)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-macos-intel.zip"
        - name: "🍎 macOS (Apple Silicon)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-macos-arm.zip"
        - name: "🐧 Linux (Intel/AMD)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-linux-amd64.tar.gz"
        - name: "🐧 Linux (ARM)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-${CI_COMMIT_TAG}-linux-arm64.tar.gz"
        - name: "BLAKE3 Checksums"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/BLAKE3SUMS.txt"
        # Raw binaries (for self-updater) - Windows first
        - name: "🪟 Windows (Intel/AMD binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-win-x86_64.exe"
        - name: "🪟 Windows (ARM binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-win-arm64.exe"
        - name: "🍎 macOS (Intel binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-macos-intel"
        - name: "🍎 macOS (Apple Silicon binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-macos-arm"
        - name: "🐧 Linux (Intel/AMD binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-linux-amd64"
        - name: "🐧 Linux (ARM binary)"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/mpv-manager/${CI_COMMIT_TAG}/mpv-manager-linux-arm64"
  tags:
    - docker
