# ────────────────────────────────────────────────────────────
# Native iOS CI/CD → DeployHub
#
# Copy this file to your iOS project:
#   .github/workflows/deployhub.yml
#
# Required GitHub Secrets:
#   DEPLOYHUB_API_KEY            – API key from DeployHub
#   DEPLOYHUB_URL                – e.g. https://deployhub-back.workzy.co
#   IOS_CERTIFICATE_BASE64       – base64 p12 cert (Development or Distribution)
#   IOS_CERTIFICATE_PASSWORD     – certificate password
#   IOS_PROVISION_PROFILE_BASE64 – base64 provisioning profile
#
# Optional Secrets:
#   DEPLOYHUB_FRONTEND_URL       – e.g. https://deployhub.workzy.co
#   XCODE_SCHEME                 – override default scheme detection
# ────────────────────────────────────────────────────────────
name: iOS → DeployHub

on:
  push:
    branches: [development]
  workflow_dispatch:
    inputs:
      release_notes:
        description: 'Release notes for this build'
        required: false
        type: string

concurrency:
  group: ios-deploy-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build-and-deploy:
    name: Build IPA & Upload to DeployHub
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Apple certificate and provisioning profile
        env:
          CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }}
          CERTIFICATE_PASSWORD: ${{ secrets.IOS_CERTIFICATE_PASSWORD }}
          PROVISION_PROFILE_BASE64: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }}
        run: |
          CERT_PATH=$RUNNER_TEMP/build_certificate.p12
          PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
          KEYCHAIN_PASSWORD=$(openssl rand -hex 16)

          echo "$CERTIFICATE_BASE64" | base64 --decode > "$CERT_PATH"
          echo "$PROVISION_PROFILE_BASE64" | base64 --decode > "$PP_PATH"

          security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
          security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"

          security import "$CERT_PATH" -P "$CERTIFICATE_PASSWORD" -A \
            -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
          security set-key-partition-list -S apple-tool:,apple: \
            -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"

          # Keep existing keychains in search list
          security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"' | tr '\n' ' ')

          # Decode the provisioning profile and install with UUID filename
          PP_DECODED=$RUNNER_TEMP/pp_decoded.plist
          security cms -D -i "$PP_PATH" > "$PP_DECODED"
          PP_UUID=$(/usr/libexec/PlistBuddy -c "Print UUID" "$PP_DECODED")

          mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
          cp "$PP_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/"${PP_UUID}.mobileprovision"

          # Read the signing identity from the keychain
          SIGN_IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | head -1 | sed 's/.*"\(.*\)"/\1/')

          # Extract profile values
          TEAM_ID=$(/usr/libexec/PlistBuddy -c "Print TeamIdentifier:0" "$PP_DECODED")
          APP_ID_FULL=$(/usr/libexec/PlistBuddy -c "Print Entitlements:application-identifier" "$PP_DECODED")
          PROFILE_BUNDLE_ID="${APP_ID_FULL#${TEAM_ID}.}"

          PP_NAME=$(/usr/libexec/PlistBuddy -c "Print Name" "$PP_DECODED" 2>/dev/null || echo "")
          GET_TASK_ALLOW=$(/usr/libexec/PlistBuddy -c "Print Entitlements:get-task-allow" "$PP_DECODED" 2>/dev/null || echo "false")
          HAS_ALL_DEVICES=$(/usr/libexec/PlistBuddy -c "Print ProvisionsAllDevices" "$PP_DECODED" 2>/dev/null || echo "false")
          HAS_DEVICES=$(/usr/libexec/PlistBuddy -c "Print ProvisionedDevices:0" "$PP_DECODED" 2>/dev/null || echo "")

          # Detect export method (using current Xcode method names)
          if [ "$HAS_ALL_DEVICES" = "true" ]; then
            METHOD="enterprise"
          elif [ "$GET_TASK_ALLOW" = "true" ]; then
            METHOD="debugging"
          elif [ -n "$HAS_DEVICES" ]; then
            METHOD="release-testing"
          else
            METHOD="app-store"
          fi

          echo "PP_UUID=$PP_UUID" >> $GITHUB_ENV
          echo "TEAM_ID=$TEAM_ID" >> $GITHUB_ENV
          echo "PROFILE_BUNDLE_ID=$PROFILE_BUNDLE_ID" >> $GITHUB_ENV
          echo "SIGN_IDENTITY=$SIGN_IDENTITY" >> $GITHUB_ENV
          echo "EXPORT_METHOD=$METHOD" >> $GITHUB_ENV

          echo "==============================="
          echo "Profile name:     $PP_NAME"
          echo "Profile UUID:     $PP_UUID"
          echo "Profile bundle:   $PROFILE_BUNDLE_ID"
          echo "Team ID:          $TEAM_ID"
          echo "Signing identity: $SIGN_IDENTITY"
          echo "get-task-allow:   $GET_TASK_ALLOW"
          echo "Export method:    $METHOD"
          echo "==============================="
          echo "Installed certificates:"
          security find-identity -v -p codesigning "$KEYCHAIN_PATH"

      - name: Detect Xcode project settings
        id: xcode
        run: |
          # Auto-detect workspace or project
          WS=$(find . -maxdepth 2 -name "*.xcworkspace" -not -path "*/Pods/*" -not -path "*/.build/*" | head -1)
          PROJ=$(find . -maxdepth 2 -name "*.xcodeproj" -not -path "*/Pods/*" | head -1)

          if [ -n "${{ secrets.XCODE_SCHEME }}" ]; then
            SCHEME="${{ secrets.XCODE_SCHEME }}"
          elif [ -n "$WS" ]; then
            SCHEME=$(xcodebuild -workspace "$WS" -list 2>/dev/null | \
                     awk '/Schemes:/{found=1; next} found && /^[[:space:]]+/{print; next} found{exit}' | \
                     head -1 | xargs)
          elif [ -n "$PROJ" ]; then
            SCHEME=$(xcodebuild -project "$PROJ" -list 2>/dev/null | \
                     awk '/Schemes:/{found=1; next} found && /^[[:space:]]+/{print; next} found{exit}' | \
                     head -1 | xargs)
          fi

          echo "workspace=$WS" >> $GITHUB_OUTPUT
          echo "project=$PROJ" >> $GITHUB_OUTPUT
          echo "scheme=$SCHEME" >> $GITHUB_OUTPUT

          # Read bundle ID from the project
          if [ "$PROFILE_BUNDLE_ID" = "*" ]; then
            if [ -n "$WS" ]; then
              BUILD_FLAG="-workspace $WS"
            else
              BUILD_FLAG="-project $PROJ"
            fi
            BUNDLE_ID=$(xcodebuild $BUILD_FLAG -scheme "$SCHEME" -showBuildSettings \
              -configuration Release 2>/dev/null \
              | grep '^\s*PRODUCT_BUNDLE_IDENTIFIER' | head -1 \
              | sed 's/.*= *//' | tr -d '[:space:]')
            echo "Wildcard profile. Bundle ID from project: $BUNDLE_ID"
          else
            BUNDLE_ID="$PROFILE_BUNDLE_ID"
          fi

          if [ -z "$BUNDLE_ID" ] || [ "$BUNDLE_ID" = "NO" ] || [ "$BUNDLE_ID" = "*" ]; then
            echo "::error::Could not detect bundle ID."
            exit 1
          fi

          echo "BUNDLE_ID=$BUNDLE_ID" >> $GITHUB_ENV

          echo "Workspace: $WS"
          echo "Project:   $PROJ"
          echo "Scheme:    $SCHEME"
          echo "Bundle ID: $BUNDLE_ID"

      - name: Install CocoaPods (if needed)
        run: |
          if [ -f "Podfile" ]; then
            pod install --repo-update
          fi

      - name: Generate ExportOptions.plist
        run: |
          printf '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n\t<key>method</key>\n\t<string>%s</string>\n\t<key>teamID</key>\n\t<string>%s</string>\n\t<key>signingCertificate</key>\n\t<string>%s</string>\n\t<key>provisioningProfiles</key>\n\t<dict>\n\t\t<key>%s</key>\n\t\t<string>%s</string>\n\t</dict>\n\t<key>signingStyle</key>\n\t<string>manual</string>\n\t<key>stripSwiftSymbols</key>\n\t<true/>\n\t<key>compileBitcode</key>\n\t<false/>\n</dict>\n</plist>\n' \
            "$EXPORT_METHOD" "$TEAM_ID" "$SIGN_IDENTITY" "$BUNDLE_ID" "$PP_UUID" \
            > "$RUNNER_TEMP/ExportOptions.plist"

          echo "--- ExportOptions.plist ---"
          cat "$RUNNER_TEMP/ExportOptions.plist"
          echo ""
          plutil -lint "$RUNNER_TEMP/ExportOptions.plist"

      - name: Configure signing in Xcode project
        run: |
          gem install xcodeproj 2>/dev/null || true

          PROJ_PATH="${{ steps.xcode.outputs.project }}"

          ruby - <<RUBY
          require 'xcodeproj'

          project = Xcodeproj::Project.open('${PROJ_PATH}')

          team_id = ENV['TEAM_ID']
          pp_uuid = ENV['PP_UUID']
          sign_id = ENV['SIGN_IDENTITY']
          bundle_id = ENV['BUNDLE_ID']

          project.targets.each do |target|
            # Only configure the main app target, skip Pods/tests/extensions
            next if target.name.include?('Pods')
            next if target.name.include?('Test')

            # Check if this target produces an app bundle
            is_app = target.product_type&.include?('application') rescue false
            next unless is_app || target.name !~ /^Pods/

            target.build_configurations.each do |config|
              config.build_settings['CODE_SIGN_STYLE'] = 'Manual'
              config.build_settings['DEVELOPMENT_TEAM'] = team_id
              config.build_settings['PROVISIONING_PROFILE_SPECIFIER'] = pp_uuid
              config.build_settings['CODE_SIGN_IDENTITY'] = sign_id
              config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = bundle_id
            end

            puts "Configured manual signing for target: #{target.name}"
          end

          project.save
          RUBY

      - name: Archive
        run: |
          SCHEME="${{ steps.xcode.outputs.scheme }}"
          WS="${{ steps.xcode.outputs.workspace }}"
          PROJ="${{ steps.xcode.outputs.project }}"

          BUILD_ARGS=(-scheme "$SCHEME" -sdk iphoneos -configuration Release \
            -destination 'generic/platform=iOS' \
            -archivePath "$RUNNER_TEMP/app.xcarchive")

          if [ -n "$WS" ]; then
            BUILD_ARGS=(-workspace "$WS" "${BUILD_ARGS[@]}")
          elif [ -n "$PROJ" ]; then
            BUILD_ARGS=(-project "$PROJ" "${BUILD_ARGS[@]}")
          fi

          xcodebuild archive "${BUILD_ARGS[@]}"

          if [ ! -d "$RUNNER_TEMP/app.xcarchive" ]; then
            echo "::error::Archive was not created."
            exit 1
          fi
          echo "Archive created successfully."

      - name: Export IPA
        run: |
          xcodebuild -exportArchive \
            -archivePath "$RUNNER_TEMP/app.xcarchive" \
            -exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist" \
            -exportPath "$RUNNER_TEMP/ipa-export" \
            -allowProvisioningUpdates

          EXPORTED_IPA=$(find "$RUNNER_TEMP/ipa-export" -name "*.ipa" -type f | head -1)
          if [ -z "$EXPORTED_IPA" ]; then
            echo "::error::Export did not produce an IPA file."
            ls -la "$RUNNER_TEMP/ipa-export/" 2>/dev/null
            exit 1
          fi
          echo "IPA exported: $EXPORTED_IPA"

      - name: Upload to DeployHub
        env:
          DEPLOYHUB_API_KEY: ${{ secrets.DEPLOYHUB_API_KEY }}
          DEPLOYHUB_URL: ${{ secrets.DEPLOYHUB_URL }}
          DEPLOYHUB_FRONTEND_URL: ${{ secrets.DEPLOYHUB_FRONTEND_URL }}
        run: |
          IPA_PATH=$(find "$RUNNER_TEMP/ipa-export" -name "*.ipa" -type f | head -1)
          echo "Uploading $(basename "$IPA_PATH")..."

          NOTES="${{ inputs.release_notes || format('Build from {0} @ {1}', github.ref_name, github.sha) }}"

          HTTP_CODE=$(curl --silent --show-error --location --max-time 600 \
            --output "$RUNNER_TEMP/upload_response.json" \
            --write-out "%{http_code}" \
            -H "X-API-Key: ${DEPLOYHUB_API_KEY}" \
            -F "file=@${IPA_PATH}" \
            -F "releaseNotes=${NOTES}" \
            "${DEPLOYHUB_URL}/api/builds/ci-upload")

          RESPONSE=$(cat "$RUNNER_TEMP/upload_response.json")
          echo "HTTP Status: $HTTP_CODE"
          echo "$RESPONSE" | jq '.' 2>/dev/null || echo "$RESPONSE"

          if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
            echo "::error::Upload failed with HTTP $HTTP_CODE"
            exit 1
          fi

          SHORT_CODE=$(echo "$RESPONSE" | jq -r '.shortCode // empty')
          VERSION=$(echo "$RESPONSE" | jq -r '.version // empty')
          APP_NAME=$(echo "$RESPONSE" | jq -r '.app.appName // empty')
          if [ -n "$SHORT_CODE" ]; then
            echo "### DeployHub Upload" >> $GITHUB_STEP_SUMMARY
            echo "- **App:** ${APP_NAME}" >> $GITHUB_STEP_SUMMARY
            echo "- **Version:** ${VERSION}" >> $GITHUB_STEP_SUMMARY
            echo "- **Short Code:** ${SHORT_CODE}" >> $GITHUB_STEP_SUMMARY
            if [ -n "${DEPLOYHUB_FRONTEND_URL:-}" ]; then
              echo "- **Install:** [${DEPLOYHUB_FRONTEND_URL}/install/${SHORT_CODE}](${DEPLOYHUB_FRONTEND_URL}/install/${SHORT_CODE})" >> $GITHUB_STEP_SUMMARY
            fi
          fi

      - name: Cleanup keychain
        if: always()
        run: |
          security delete-keychain $RUNNER_TEMP/app-signing.keychain-db 2>/dev/null || true
