name: Build MCC and Documents

on:
  push:
    branches:
      - master
  workflow_dispatch:
  
env:
  PROJECT: "MinecraftClient"
  target-version: "net10.0"
  dotnet-version: "10.0.x"
  compile-flags: "--self-contained=true -c Release -p:UseAppHost=true -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:DebugType=Embedded -p:PublishSingleFile=true"

jobs:
  determine-build:
    runs-on: ubuntu-slim
    outputs:
      skip: ${{ steps.check-skip.outputs.skip }}
    steps:
    - name: Check skip CI
      id: check-skip
      run: |
        LOWER=$(echo "$COMMIT_MSG" | tr '[:upper:]' '[:lower:]')
        if echo "$LOWER" | grep -qE 'skip.?ci|ci.?skip'; then
          echo "skip=true" >> $GITHUB_OUTPUT
        else
          echo "skip=false" >> $GITHUB_OUTPUT
        fi
      env:
        COMMIT_MSG: ${{ github.event.head_commit.message }}

  fetch-translations:
    strategy:
      fail-fast: true
    runs-on: ubuntu-latest
    needs: determine-build

    if: ${{ needs.determine-build.outputs.skip != 'true' }}

    timeout-minutes: 15

    steps:
    - name: Check cache
      uses: actions/cache/restore@v3
      id: cache-check
      with:
        path: ${{ github.workspace }}/*
        key: "translation-${{ github.sha }}"
        lookup-only: true
        restore-keys: "translation-"

    - name: Checkout
      if: steps.cache-check.outputs.cache-hit != 'true'
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
        submodules: 'true'

    - name: Check Crowdin secrets
      id: crowdin-check
      run: |
        if [ -z "$CROWDIN_PROJECT_ID" ] || [ -z "$CROWDIN_PERSONAL_TOKEN" ]; then
          echo "available=false" >> $GITHUB_OUTPUT
        else
          echo "available=true" >> $GITHUB_OUTPUT
        fi
      env:
        CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
        CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_TOKEN }}

    - name: Download translations from crowdin
      uses: crowdin/github-action@v2.4.0
      if: steps.cache-check.outputs.cache-hit != 'true' && steps.crowdin-check.outputs.available == 'true'
      with:
        upload_sources: ${{ github.repository == 'MCCTeam/Minecraft-Console-Client' }}
        upload_translations: false
        download_translations: true

        localization_branch_name: l10n_master
        create_pull_request: false 
        push_translations: false

        base_path: ${{ github.workspace }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
        CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
      
    - name: Save cache
      uses: actions/cache/save@v3
      if: steps.cache-check.outputs.cache-hit != 'true'
      with:
        path:  ${{ github.workspace }}/*
        key: "translation-${{ github.sha }}"

  create-tag:
    runs-on: ubuntu-slim
    timeout-minutes: 5 # Wait 5 minutes in case of network issues/etc
    needs: determine-build
    if: ${{ needs.determine-build.outputs.skip != 'true' }}
    steps:
      - id: make-tag
        run: |
          TAG="$(date -u +'%Y%m%d')-${{ github.run_number }}"
          echo "tag=$TAG" >> $GITHUB_OUTPUT
          echo "TAG=$TAG" >> $GITHUB_ENV
      
      - name: Create Release Tag
        uses: actions/github-script@v7
        with:
          script: |
            const tag = process.env.TAG;
            try {
                await github.rest.git.createRef({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  ref: `refs/tags/${tag}`,
                  sha: context.sha
                });
              } catch(error) {
                if (error.message.includes('already exists')) {
                  console.log(`Tag ${tag} already exists`);
                } else {
                  throw error;
                }
              }
    outputs:
      build-tag: ${{ steps.make-tag.outputs.tag }}

  build:
    runs-on: ubuntu-latest
    # Check if we're not skipping build, tag is created, and translations successfully fetched (or skipped)
    if: ${{ needs.determine-build.outputs.skip != 'true' &&
            needs.create-tag.result == 'success' &&
            (needs.fetch-translations.result == 'success' || needs.fetch-translations.result == 'skipped')
          }}
    needs: [determine-build, fetch-translations, create-tag]
    timeout-minutes: 15
    strategy:
      matrix:
        target: [win-x86, win-x64, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, osx-arm64]

    steps:
    - name: Checkout
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
        submodules: 'true'
        
    - name: Get Current Date
      run: |
        echo date_dashed=$(date -u +'%Y-%m-%d') >> $GITHUB_ENV
        
    - name: Restore Translations (if available)
      uses: actions/cache/restore@v3
      with:
        path: ${{ github.workspace }}/*
        key: "translation-${{ github.sha }}"
        restore-keys: "translation-"
          
    - name: Setup .NET SDK
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: ${{ env.dotnet-version }}
        
    - name: Setup Environment Variables
      run: |
        PROJECT_PATH=${{ github.workspace }}/${{ env.PROJECT }}
        FILE_EXT=${{ (startsWith(matrix.target, 'win') && '.exe') || '' }}
        TARGET_OUT_PATH=$PROJECT_PATH/bin/Release/${{ env.target-version }}/${{ matrix.target }}/publish/
    
        echo "project-path=$PROJECT_PATH" >> $GITHUB_ENV
        echo "file-ext=$FILE_EXT" >> $GITHUB_ENV
        echo "target-out-path=$TARGET_OUT_PATH" >> $GITHUB_ENV
        echo "assembly-info=$PROJECT_PATH/Properties/AssemblyInfo.cs" >> $GITHUB_ENV
        echo "build-version-info=${{ needs.create-tag.outputs.build-tag }}" >> $GITHUB_ENV
        echo "commit=$(echo ${{ github.sha }} | cut -c 1-7)" >> $GITHUB_ENV
        
    - name: Setup Binaries Path
      run: |
        echo built-executable-path=${{ env.target-out-path }}${{ env.PROJECT }}${{ env.file-ext }} >> $GITHUB_ENV

    - name: Set Version Info
      run: |
        echo '' >> ${{ env.assembly-info }}
        echo "[assembly: AssemblyConfiguration(\"GitHub build ${{ github.run_number }}, built on ${{ env.date_dashed }} from commit ${{ env.commit }}\")]" >> ${{ env.assembly-info }}
        
    - name: Inject Sentry DSN (if applicable)
      if: ${{ github.repository == 'MCCTeam/Minecraft-Console-Client' }}
      run: |
        grep -q 'SentryDSN = "";' ${{ env.project-path }}/Program.cs || { echo "SentryDSN pattern not found in Program.cs"; exit 1; }
        sed -i -e 's|SentryDSN = "";|SentryDSN = "${{ secrets.SENTRY_DSN }}";|g' ${{ env.project-path }}/Program.cs

    - name: Build Target
      run: dotnet publish ${{ env.project-path }}/${{ env.PROJECT }}.csproj -f ${{ env.target-version }} -r ${{ matrix.target }} ${{ env.compile-flags }}
      env:
        DOTNET_NOLOGO: true

    - name: Rename Binary
      run: |
        mv ${{ env.built-executable-path }} ${{ env.PROJECT }}-${{ env.build-version-info }}-${{ matrix.target }}${{ env.file-ext }}

    - name: Upload Artifact
      uses: actions/upload-artifact@v4
      with:
        name: ${{ env.PROJECT }}-${{ env.build-version-info }}-${{ matrix.target }}
        path: ${{ env.PROJECT }}-${{ env.build-version-info }}-${{ matrix.target }}${{ env.file-ext }}
        if-no-files-found: error

  create-release:
    runs-on: ubuntu-slim
    needs: [create-tag, build]
    if: ${{ needs.build.result == 'success' && needs.create-tag.result == 'success' }}
    steps:
      - name: Download All Artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts/
          merge-multiple: true

      - name: Truncate commit message for release name
        id: release-name
        run: |
           SUBJECT=$(echo "$COMMIT_MSG" | head -n 1)
           MAX=220
           TRUNCATED="${SUBJECT:0:$MAX}"
           echo "name=${BUILD_TAG}: $TRUNCATED" >> $GITHUB_OUTPUT
        env:
          COMMIT_MSG: ${{ github.event.head_commit.message }}
          BUILD_TAG: ${{ needs.create-tag.outputs.build-tag }}
          
      - name: Create Release
        uses: ncipollo/release-action@v1.14.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          artifacts: "artifacts/**/*"
          tag: ${{ needs.create-tag.outputs.build-tag }}
          name: ${{ steps.release-name.outputs.name }}
          generateReleaseNotes: true
          artifactErrorsFailBuild: true
          allowUpdates: true
          makeLatest: true
          omitBodyDuringUpdate: true
          omitNameDuringUpdate: true
          replacesArtifacts: true
