name: Execute Documentation Sync

on:
  workflow_run:
    workflows: ["Analyze Documentation Changes"]
    types:
      - completed
    branches: [main, revamp]
  workflow_dispatch:
    inputs:
      pr_number:
        description: 'PR number to process'
        required: true
        type: string

permissions:
  contents: write
  pull-requests: write
  actions: read

jobs:
  execute-sync:
    runs-on: ubuntu-latest
    if: |
      (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
      github.event_name == 'workflow_dispatch'
    steps:
      - name: Check workflow source
        id: check-source
        run: |
          echo "Checking workflow source..."
          echo "Event name: ${{ github.event_name }}"
          
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            # Manual trigger - bypass source checks for revamp branch
            if [[ "${{ github.ref }}" == "refs/heads/revamp" ]]; then
              echo "Manual workflow_dispatch on revamp branch - proceeding"
              echo "is_fork=false" >> $GITHUB_OUTPUT
              echo "should_process=true" >> $GITHUB_OUTPUT
            else
              echo "Manual workflow_dispatch not on revamp branch - skipping"
              echo "should_process=false" >> $GITHUB_OUTPUT
            fi
          else
            # workflow_run event - use existing logic
            echo "Event: ${{ github.event.workflow_run.event }}"
            echo "Repository: ${{ github.event.workflow_run.repository.full_name }}"
            echo "Head Repository: ${{ github.event.workflow_run.head_repository.full_name }}"
            echo "Head Branch: ${{ github.event.workflow_run.head_branch }}"
            
            # Security check: Only process PRs from the same repository or trusted forks
            if [[ "${{ github.event.workflow_run.event }}" != "pull_request" ]]; then
              echo "Not a pull request event, skipping"
              echo "should_process=false" >> $GITHUB_OUTPUT
              exit 0
            fi
            
            # Check if this is from a fork
            IS_FORK="false"
            if [[ "${{ github.event.workflow_run.repository.full_name }}" != "${{ github.event.workflow_run.head_repository.full_name }}" ]]; then
              IS_FORK="true"
            fi
            
            echo "is_fork=$IS_FORK" >> $GITHUB_OUTPUT
            echo "should_process=true" >> $GITHUB_OUTPUT
          fi

      - name: Download analysis artifacts
        if: steps.check-source.outputs.should_process == 'true'
        uses: actions/github-script@v7
        id: download-artifacts
        with:
          script: |
            const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
              owner: context.repo.owner,
              repo: context.repo.repo,
              run_id: ${{ github.event.workflow_run.id }}
            });
            
            const matchArtifact = artifacts.data.artifacts.find(artifact => {
              return artifact.name.startsWith('docs-sync-analysis-');
            });
            
            if (!matchArtifact) {
              console.log('No analysis artifacts found');
              return false;
            }
            
            const download = await github.rest.actions.downloadArtifact({
              owner: context.repo.owner,
              repo: context.repo.repo,
              artifact_id: matchArtifact.id,
              archive_format: 'zip'
            });
            
            const fs = require('fs');
            fs.writeFileSync('/tmp/artifacts.zip', Buffer.from(download.data));
            
            // Extract PR number from artifact name
            const prNumber = matchArtifact.name.split('-').pop();
            core.setOutput('pr_number', prNumber);
            core.setOutput('artifact_found', 'true');
            
            return true;

      - name: Extract and validate artifacts
        if: steps.download-artifacts.outputs.artifact_found == 'true'
        id: extract-artifacts
        run: |
          echo "Extracting artifacts..."
          
          # Create secure temporary directory
          WORK_DIR=$(mktemp -d /tmp/sync-XXXXXX)
          echo "work_dir=$WORK_DIR" >> $GITHUB_OUTPUT
          
          # Extract to temporary directory
          cd "$WORK_DIR"
          unzip /tmp/artifacts.zip
          
          # Validate extracted files
          REQUIRED_FILES="analysis.json sync_plan.json changed_files.txt"
          for file in $REQUIRED_FILES; do
            if [ ! -f "$file" ]; then
              echo "Error: Required file $file not found"
              exit 1
            fi
          done
          
          # Validate JSON structure
          python3 -c "
          import json
          import sys
          
          try:
              with open('analysis.json') as f:
                  analysis = json.load(f)
              with open('sync_plan.json') as f:
                  sync_plan = json.load(f)
              
              # Validate required fields
              assert 'pr_number' in analysis
              assert 'files_to_sync' in sync_plan
              assert 'target_languages' in sync_plan
              
              print('Artifacts validated successfully')
          except Exception as e:
              print(f'Validation error: {e}')
              sys.exit(1)
          "
          
          # Extract PR number and other metadata
          PR_NUMBER=$(python3 -c "import json; print(json.load(open('analysis.json'))['pr_number'])")
          echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
          
          # Check if sync is required
          SYNC_REQUIRED=$(python3 -c "import json; print(str(json.load(open('sync_plan.json'))['sync_required']).lower())")
          echo "sync_required=$SYNC_REQUIRED" >> $GITHUB_OUTPUT

      - name: Checkout base repository
        if: steps.extract-artifacts.outputs.sync_required == 'true'
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0

      - name: Set up Python
        if: steps.extract-artifacts.outputs.sync_required == 'true'
        uses: actions/setup-python@v4
        with:
          python-version: '3.9'

      - name: Install dependencies
        if: steps.extract-artifacts.outputs.sync_required == 'true'
        run: |
          cd tools/translate
          pip install httpx aiofiles python-dotenv

      - name: Check for manual approval requirement
        if: steps.extract-artifacts.outputs.sync_required == 'true' && steps.check-source.outputs.is_fork == 'true'
        id: check-approval
        uses: actions/github-script@v7
        with:
          script: |
            const prNumber = ${{ steps.extract-artifacts.outputs.pr_number }};
            
            // Get PR details
            const pr = await github.rest.pulls.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: prNumber
            });
            
            const author = pr.data.user.login;
            const authorAssociation = pr.data.author_association;
            
            // Check if author is trusted
            const trustedAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR'];
            const trustedContributors = process.env.TRUSTED_CONTRIBUTORS?.split(',') || [];
            
            const isTrusted = trustedAssociations.includes(authorAssociation) || 
                             trustedContributors.includes(author);
            
            if (!isTrusted) {
              // Check for approval from maintainer
              const reviews = await github.rest.pulls.listReviews({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: prNumber
              });
              
              const hasApproval = reviews.data.some(review => 
                review.state === 'APPROVED' && 
                trustedAssociations.includes(review.author_association)
              );
              
              if (!hasApproval) {
                console.log('PR requires manual approval from a maintainer');
                core.setOutput('needs_approval', 'true');
                
                // Comment on PR
                await github.rest.issues.createComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: prNumber,
                  body: '⏸️ **Documentation sync is pending approval**\n\n' +
                        'This PR requires approval from a maintainer before automatic synchronization can proceed.\n\n' +
                        'Once approved, the documentation will be automatically translated and synchronized.'
                });
                
                return;
              }
            }
            
            core.setOutput('needs_approval', 'false');

      - name: Execute safe synchronization
        if: steps.extract-artifacts.outputs.sync_required == 'true' && steps.check-approval.outputs.needs_approval != 'true'
        id: sync
        env:
          DIFY_API_KEY: ${{ secrets.DIFY_API_KEY }}
        run: |
          echo "Executing documentation synchronization..."
          
          WORK_DIR="${{ steps.extract-artifacts.outputs.work_dir }}"
          PR_NUMBER="${{ steps.extract-artifacts.outputs.pr_number }}"
          
          # Create a new branch for the sync results
          SYNC_BRANCH="docs-sync-pr-${PR_NUMBER}"
          git checkout -b "$SYNC_BRANCH"
          
          # Run synchronization with security constraints
          cd tools/translate
          
          # Create a secure sync script
          cat > secure_sync.py <<'EOF'
          import json
          import sys
          import os
          import asyncio
          from pathlib import Path
          
          # Add parent directory to path
          sys.path.append(os.path.dirname(__file__))
          from sync_and_translate import DocsSynchronizer
          
          async def secure_sync():
              work_dir = sys.argv[1]
              
              # Load sync plan
              with open(f"{work_dir}/sync_plan.json") as f:
                  sync_plan = json.load(f)
              
              # Security: Only sync files from the approved list
              files_to_sync = sync_plan.get("files_to_sync", [])
              
              # Validate file paths again
              for file_info in files_to_sync:
                  file_path = file_info["path"]
                  
                  # Security checks
                  if ".." in file_path or file_path.startswith("/"):
                      print(f"Security error: Invalid path {file_path}")
                      return False
                  
                  if not file_path.startswith("en/"):
                      print(f"Security error: File outside en/ directory: {file_path}")
                      return False
              
              # Initialize synchronizer
              api_key = os.environ.get("DIFY_API_KEY")
              if not api_key:
                  print("Error: DIFY_API_KEY not set")
                  return False
              
              synchronizer = DocsSynchronizer(api_key)
              
              # Perform limited sync
              results = {
                  "translated": [],
                  "failed": [],
                  "skipped": []
              }
              
              for file_info in files_to_sync[:10]:  # Limit to 10 files
                  file_path = file_info["path"]
                  print(f"Processing: {file_path}")
                  
                  try:
                      # Only translate if file exists and is safe
                      if os.path.exists(f"../../{file_path}"):
                          for target_lang in ["zh-hans", "ja-jp"]:
                              target_path = file_path.replace("en/", f"{target_lang}/")
                              success = await synchronizer.translate_file_with_notice(
                                  file_path,
                                  target_path,
                                  target_lang
                              )
                              if success:
                                  results["translated"].append(target_path)
                              else:
                                  results["failed"].append(target_path)
                      else:
                          results["skipped"].append(file_path)
                  except Exception as e:
                      print(f"Error processing {file_path}: {e}")
                      results["failed"].append(file_path)
              
              # Handle docs.json structure sync if needed
              if sync_plan.get("structure_changes", {}).get("structure_changed"):
                  print("Syncing docs.json structure...")
                  try:
                      sync_log = synchronizer.sync_docs_json_structure()
                      print("\n".join(sync_log))
                  except Exception as e:
                      print(f"Error syncing structure: {e}")
              
              # Save results
              with open("/tmp/sync_results.json", "w") as f:
                  json.dump(results, f, indent=2)
              
              return len(results["failed"]) == 0
          
          if __name__ == "__main__":
              success = asyncio.run(secure_sync())
              sys.exit(0 if success else 1)
          EOF
          
          # Run the secure sync
          python secure_sync.py "$WORK_DIR"
          SYNC_EXIT_CODE=$?
          
          echo "sync_exit_code=$SYNC_EXIT_CODE" >> $GITHUB_OUTPUT
          
          # Check for changes
          if [[ -n $(git status --porcelain) ]]; then
            echo "has_changes=true" >> $GITHUB_OUTPUT
          else
            echo "has_changes=false" >> $GITHUB_OUTPUT
          fi

      - name: Commit and create translation PR
        if: steps.sync.outputs.has_changes == 'true'
        id: create-translation-pr
        run: |
          PR_NUMBER="${{ steps.extract-artifacts.outputs.pr_number }}"
          SYNC_BRANCH="docs-sync-pr-${PR_NUMBER}"
          
          git config user.name 'github-actions[bot]'
          git config user.email 'github-actions[bot]@users.noreply.github.com'
          
          # Commit translation changes
          git add .
          git commit -m "🌐 Auto-translate documentation for PR #${PR_NUMBER}

          Auto-generated translations for documentation changes in PR #${PR_NUMBER}.
          
          Original PR: #${PR_NUMBER}
          Languages: Chinese (zh-hans), Japanese (ja-jp)
          
          🤖 Generated with GitHub Actions"
          
          # Push the translation branch to main repo
          git push origin "$SYNC_BRANCH" --force
          
          # Get original PR details for translation PR
          ORIGINAL_PR_TITLE=$(gh pr view ${PR_NUMBER} --json title --jq '.title' 2>/dev/null || echo "Documentation changes")
          
          # Create translation PR body
          cat > /tmp/translation_pr_body.md <<EOF
          # 🌐 Auto-generated Translations
          
          This PR contains automatically generated translations for the documentation changes in PR #${PR_NUMBER}.
          
          ## Original PR
          **Title:** ${ORIGINAL_PR_TITLE}  
          **Link:** #${PR_NUMBER}
          
          ## What's included
          - 🇨🇳 Chinese (zh-hans) translations
          - 🇯🇵 Japanese (ja-jp) translations
          - 📋 Updated navigation structure in docs.json
          
          ## Review Process
          1. Review the generated translations for accuracy
          2. Make any necessary adjustments
          3. Merge this PR to apply the translations
          
          ## Links
          - **Original English PR:** #${PR_NUMBER}
          - **Translation branch:** \`${SYNC_BRANCH}\`
          
          ---
          🤖 This PR was created automatically by the documentation translation workflow.
          EOF
          
          # Create the translation PR
          TRANSLATION_PR_URL=$(gh pr create \
            --base main \
            --head "$SYNC_BRANCH" \
            --title "🌐 Auto-translations for PR #${PR_NUMBER}: ${ORIGINAL_PR_TITLE}" \
            --body-file /tmp/translation_pr_body.md \
            --label "🌐 translation" \
            --label "🤖 automated" 2>/dev/null || echo "")
          
          if [ -n "$TRANSLATION_PR_URL" ]; then
            # Extract PR number from URL
            TRANSLATION_PR_NUMBER=$(echo "$TRANSLATION_PR_URL" | grep -o '[0-9]\+$')
            echo "translation_pr_number=$TRANSLATION_PR_NUMBER" >> $GITHUB_OUTPUT
            echo "translation_pr_url=$TRANSLATION_PR_URL" >> $GITHUB_OUTPUT
            echo "branch_name=$SYNC_BRANCH" >> $GITHUB_OUTPUT
            echo "creation_successful=true" >> $GITHUB_OUTPUT
            
            echo "✅ Translation PR created successfully: #${TRANSLATION_PR_NUMBER}"
          else
            echo "❌ Failed to create translation PR"
            echo "creation_successful=false" >> $GITHUB_OUTPUT
          fi

      - name: Comment on original PR with translation PR link
        if: steps.extract-artifacts.outputs.sync_required == 'true' && steps.check-approval.outputs.needs_approval != 'true'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const prNumber = ${{ steps.extract-artifacts.outputs.pr_number }};
            const hasChanges = '${{ steps.sync.outputs.has_changes }}' === 'true';
            const translationPrNumber = '${{ steps.create-translation-pr.outputs.translation_pr_number }}';
            const translationPrUrl = '${{ steps.create-translation-pr.outputs.translation_pr_url }}';
            const creationSuccessful = '${{ steps.create-translation-pr.outputs.creation_successful }}' === 'true';
            
            let comment = '## 🤖 Automatic Translation Status\n\n';
            
            if (hasChanges && creationSuccessful && translationPrNumber) {
              // Load sync results if available
              let results = { translated: [], failed: [], skipped: [] };
              try {
                results = JSON.parse(fs.readFileSync('/tmp/sync_results.json', 'utf8'));
              } catch (e) {
                console.log('Could not load sync results');
                results = { translated: [], failed: [], skipped: [] };
              }
              
              comment += `🎉 **Translation PR Created Successfully!**\n\n`;
              comment += `Your English documentation changes have been automatically translated and a separate PR has been created.\n\n`;
              comment += `### 🔗 Translation PR: [#${translationPrNumber}](${translationPrUrl})\n\n`;
              
              if (results.translated && results.translated.length > 0) {
                comment += `### ✅ Successfully Translated (${results.translated.length} files):\n`;
                results.translated.slice(0, 8).forEach(file => {
                  comment += `- \`${file}\`\n`;
                });
                if (results.translated.length > 8) {
                  comment += `- ... and ${results.translated.length - 8} more files\n`;
                }
                comment += '\n';
              }
              
              if (results.failed && results.failed.length > 0) {
                comment += `### ⚠️ Translation Issues (${results.failed.length}):\n`;
                results.failed.slice(0, 5).forEach(file => {
                  comment += `- \`${file}\`\n`;
                });
                if (results.failed.length > 5) {
                  comment += `- ... and ${results.failed.length - 5} more\n`;
                }
                comment += '\n';
              }
              
              comment += '### 🔄 What Happens Next:\n';
              comment += `1. **Review**: The translation PR [#${translationPrNumber}](${translationPrUrl}) is ready for review\n`;
              comment += '2. **Independent**: Both PRs can be reviewed and merged independently\n';
              comment += '3. **Automatic**: Future updates to this PR will automatically update the translation PR\n\n';
              
              comment += '### 📋 Languages Included:\n';
              comment += '- 🇨🇳 **Chinese (zh-hans)**: Simplified Chinese translations\n';
              comment += '- 🇯🇵 **Japanese (ja-jp)**: Japanese translations\n';
              comment += '- 📋 **Navigation**: Updated docs.json structure for both languages\n\n';
              
              comment += '---\n';
              comment += '_🤖 This is an automated translation workflow. The translation PR was created automatically and is ready for review._';
              
            } else if (hasChanges && !creationSuccessful) {
              comment += '⚠️ **Translation PR Creation Failed**\n\n';
              comment += 'The automatic translation process completed, but there was an issue creating the translation PR.\n\n';
              comment += '**What you can do:**\n';
              comment += '1. Check the workflow logs for detailed error information\n';
              comment += '2. Contact a maintainer if the issue persists\n';
              comment += '3. The translations may have been generated but need manual PR creation\n\n';
              comment += '_🤖 This is an automated notification from the translation workflow._';
              
            } else {
              comment += '✅ **No Translation Changes Needed**\n\n';
              comment += 'Your changes did not require new translations, or all translations are already up to date.\n\n';
              comment += '_🤖 This is an automated check from the translation workflow._';
            }
            
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber,
              body: comment
            });

      - name: Comment on translation PR with original PR link
        if: steps.create-translation-pr.outputs.creation_successful == 'true' && steps.create-translation-pr.outputs.translation_pr_number
        uses: actions/github-script@v7
        continue-on-error: true
        with:
          script: |
            const prNumber = ${{ steps.extract-artifacts.outputs.pr_number }};
            const translationPrNumber = ${{ steps.create-translation-pr.outputs.translation_pr_number }};
            
            const backLinkComment = [
              '## 🔗 Linked to Original PR',
              '',
              `This translation PR was automatically created for the English documentation changes in **PR #${prNumber}**.`,
              '',
              '### 📝 Original Changes',
              `- **Original PR**: #${prNumber}`,
              '- **Type**: English documentation updates',
              '- **Auto-translation**: This PR contains the corresponding translations',
              '',
              '### 🔄 Synchronization',
              '- **Automatic Updates**: This PR will be automatically updated if the original PR changes',
              '- **Independent Review**: This translation PR can be reviewed and merged independently',
              '- **Quality Check**: Please review translations for accuracy and cultural appropriateness',
              '',
              '---',
              `🤖 _This PR is part of the automated translation workflow. Any updates to PR #${prNumber} will automatically update this translation PR._`
            ].join('\\n');

            try {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: translationPrNumber,
                body: backLinkComment
              });
              console.log(`Successfully linked translation PR #${translationPrNumber} to original PR #${prNumber}`);
            } catch (error) {
              console.log(`Could not comment on translation PR #${translationPrNumber}:`, error.message);
            }

  handle-failure:
    runs-on: ubuntu-latest
    if: github.event.workflow_run.conclusion == 'failure'
    steps:
      - name: Report analysis failure
        uses: actions/github-script@v7
        with:
          script: |
            // Try to extract PR number from workflow run
            const workflowRun = context.payload.workflow_run;
            
            console.log('Analysis workflow failed');
            console.log('Attempting to notify PR if possible...');
            
            // This is a best-effort attempt to notify
            // In practice, you might want to store PR number differently