name: Sync CMP Directories
on:
  workflow_dispatch:
    inputs:
      upstream:
        description: 'Upstream repository to sync directories from'
        default: 'https://github.com/openMF/kmp-project-template.git'
        required: true
        type: string
  schedule:
    - cron: '0 0 * * 1'

jobs:
  sync-directories:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: dev

      - name: Setup Git config
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"

      - name: Add upstream remote and fetch
        run: |
          git remote add upstream ${{ inputs.upstream }} || true
          git fetch upstream || exit 1

      - name: Check upstream/dev exists
        run: |
          if ! git rev-parse --verify upstream/dev >/dev/null 2>&1; then
            echo "Error: upstream/dev branch does not exist"
            exit 1
          fi

      - name: Create and checkout temporary branch
        run: |
          TEMP_BRANCH="temp-sync-branch-${{ github.run_number }}"
          git checkout -b "$TEMP_BRANCH" upstream/dev || exit 1
          echo "TEMP_BRANCH=$TEMP_BRANCH" >> $GITHUB_ENV

      - name: Sync directories and files
        run: |
          # Declare directories and files to sync
          DIRS=(
            "cmp-android"
            "cmp-desktop"
            "cmp-ios"
            "cmp-web"
            "cmp-shared"
            "core-base"
            "build-logic"
            "fastlane"
            "scripts"
            "config"
            ".github"
            ".run"
          )
          
          FILES=(
            "Gemfile"
            "Gemfile.lock"
            "ci-prepush.bat"
            "ci-prepush.sh"
          )
          
          # Define exclusions
          declare -A EXCLUSIONS=(
            ["cmp-android"]="src/main/res dependencies src/main/ic_launcher-playstore.png google-services.json"
            ["cmp-web"]="src/jsMain/resources src/wasmJsMain/resources"
            ["cmp-desktop"]="icons"
            ["cmp-ios"]="iosApp/Assets.xcassets"
            ["root"]="secrets.env"
          )
          
          # Function to check if path should be excluded
          should_exclude() {
            local dir=$1
            local path=$2
          
            # Check for root exclusions
            if [[ "$dir" == "." && -n "${EXCLUSIONS["root"]}" ]]; then
              local root_excluded_paths=(${EXCLUSIONS["root"]})
              for excluded in "${root_excluded_paths[@]}"; do
                if [[ "$path" == *"$excluded"* ]]; then
                  return 0
                fi
              done
            fi
          
            # Check directory-specific exclusions
            if [[ -n "${EXCLUSIONS[$dir]}" ]]; then
              local excluded_paths=(${EXCLUSIONS[$dir]})
              for excluded in "${excluded_paths[@]}"; do
                if [[ "$path" == *"$excluded"* ]]; then
                  return 0
                fi
              done
            fi
            return 1
          }
          
          # Function to preserve excluded paths
          preserve_excluded() {
            local dir=$1
            if [[ -n "${EXCLUSIONS[$dir]}" ]]; then
              local excluded_paths=(${EXCLUSIONS[$dir]})
              for excluded in "${excluded_paths[@]}"; do
                local full_path="$dir/$excluded"
                if [[ -e "$full_path" ]]; then
                  echo "Preserving excluded path: $full_path"
                  local temp_path="temp_excluded/$full_path"
                  mkdir -p "$(dirname "$temp_path")"
                  cp -r "$full_path" "$(dirname "$temp_path")"
                fi
              done
            fi
          }
          
          # Function to restore excluded paths
          restore_excluded() {
            local dir=$1
            if [[ -n "${EXCLUSIONS[$dir]}" ]]; then
              local excluded_paths=(${EXCLUSIONS[$dir]})
              for excluded in "${excluded_paths[@]}"; do
                local full_path="$dir/$excluded"
                local temp_path="temp_excluded/$full_path"
                if [[ -e "$temp_path" ]]; then
                  echo "Restoring excluded path: $full_path"
                  mkdir -p "$(dirname "$full_path")"
                  rm -rf "$full_path"
                  cp -r "$temp_path" "$(dirname "$full_path")"
                fi
              done
            fi
          }
          
          # Function to preserve root-level excluded files
          preserve_root_files() {
            if [[ -n "${EXCLUSIONS["root"]}" ]]; then
              local excluded_paths=(${EXCLUSIONS["root"]})
              for excluded in "${excluded_paths[@]}"; do
                if [[ -e "$excluded" ]]; then
                  echo "Preserving root-level excluded file: $excluded"
                  mkdir -p "temp_excluded/root"
                  cp -r "$excluded" "temp_excluded/root/"
                fi
              done
            fi
          }
          
          # Function to restore root-level excluded files
          restore_root_files() {
            if [[ -n "${EXCLUSIONS["root"]}" ]]; then
              local excluded_paths=(${EXCLUSIONS["root"]})
              for excluded in "${excluded_paths[@]}"; do
                if [[ -e "temp_excluded/root/$excluded" ]]; then
                  echo "Restoring root-level excluded file: $excluded"
                  cp -r "temp_excluded/root/$excluded" "./"
                fi
              done
            fi
          }
          
          # Create temp directory for exclusions
          mkdir -p temp_excluded
          
          # Preserve root-level exclusions before sync
          preserve_root_files
          
          # Switch to dev branch
          git checkout dev
          
          # Sync directories
          for dir in "${DIRS[@]}"; do
            if [ ! -d "$dir" ]; then
              echo "Creating $dir..."
              mkdir -p "$dir"
            fi
          
            # Preserve excluded paths before sync
            if [[ -d "$dir" ]]; then
              preserve_excluded "$dir"
            fi
          
            echo "Syncing $dir..."
            git checkout "${{ env.TEMP_BRANCH }}" -- "$dir" || exit 1
          
            # Restore excluded paths after sync
            restore_excluded "$dir"
          done
          
          # Sync files
          for file in "${FILES[@]}"; do
            dir=$(dirname "$file")
            if ! should_exclude "$dir" "$file"; then
              echo "Syncing $file..."
              git checkout "${{ env.TEMP_BRANCH }}" -- "$file" || true
            else
              echo "Skipping excluded file: $file"
            fi
          done
          
          # Restore root-level excluded files
          restore_root_files
          
          # Cleanup temp directory
          rm -rf temp_excluded

      - name: Clean up temporary branch
        if: always()
        run: git branch -D "${{ env.TEMP_BRANCH }}" || true

      - name: Check for changes
        id: check_changes
        run: |
          if [[ -n "$(git status --porcelain)" ]]; then
            echo "has_changes=true" >> $GITHUB_OUTPUT
          else
            echo "has_changes=false" >> $GITHUB_OUTPUT
          fi

      - name: Create Pull Request
        if: steps.check_changes.outputs.has_changes == 'true'
        uses: peter-evans/create-pull-request@v7
        with:
          token: ${{ secrets.PAT_TOKEN }}
          commit-message: "chore: Sync directories and files from upstream"
          title: "chore: Sync directories and files from upstream"
          body: |
            Automated sync of directories and files from upstream repository.
            
            Changes included in this sync:
            
            Directories:
            - cmp-android (excluding src/main/res, dependencies, ic_launcher-playstore.png, google-services.json)
            - cmp-desktop (excluding icons)
            - cmp-ios (excluding iosApp/Assets.xcassets)
            - cmp-web (excluding src/jsMain/resources, src/wasmJsMain/resources)
            - cmp-shared
            - build-logic
            - fastlane
            - scripts
            - config
            - .github
            - .run
            
            Files:
            - Gemfile
            - Gemfile.lock
            - ci-prepush.bat
            - ci-prepush.sh
            
            Root-level exclusions:
            - secrets.env
            
            Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
          branch: sync-dirs-${{ github.run_number }}
          delete-branch: true
          labels: |
            sync
            automated pr
          base: dev
