name: FHIR IG CI/CD Pipeline with Version Persistence

on:
  push:
    branches: [ main, develop ]
    tags:
      - 'v*.*.*'  # Trigger on version tags like v0.3.0
  pull_request:
    branches: [ main ]

env:
  REGISTRY: git.dghs.gov.bd
  IMAGE_NAME: gitadmin/bd-core-fhir-ig

jobs:
  build-ig:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout repository
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
    
    - name: Extract version from IG
      id: version
      run: |
        # Extract version from ImplementationGuide resource
        VERSION=$(grep -oP '<version value="\K[^"]+' input/bd.fhir.core.xml | head -1)
        
        if [ -z "$VERSION" ]; then
          echo "ERROR: Could not extract version from ImplementationGuide XML"
          exit 1
        fi
        
        echo "Extracted version: $VERSION"
        echo "version=$VERSION" >> $GITHUB_OUTPUT
        
        # Determine if this is a release build (git tag) or dev build
        if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
          BUILD_TYPE="release"
          TAG_VERSION="${GITHUB_REF#refs/tags/v}"
          
          # Verify tag matches IG version
          if [ "$TAG_VERSION" != "$VERSION" ]; then
            echo "ERROR: Git tag version ($TAG_VERSION) doesn't match IG version ($VERSION)"
            exit 1
          fi
        else
          BUILD_TYPE="dev"
        fi
        
        echo "build_type=$BUILD_TYPE" >> $GITHUB_OUTPUT
        echo "Build type: $BUILD_TYPE"
    
    - name: Install Docker CLI
      run: |
        apt-get update
        apt-get install -y docker.io
        docker --version
    
    - name: Build FHIR IG
      run: |
        echo "Building FHIR IG version ${{ steps.version.outputs.version }}..."
        
        CONTAINER_ID=$(docker create \
          hl7fhir/ig-publisher-base:latest \
          /bin/bash -c "cp -r /home/publisher/ig /tmp/build && cd /tmp/build && _updatePublisher.sh -y && _genonce.sh")
        
        echo "Container ID: $CONTAINER_ID"
        
        docker cp $(pwd)/. $CONTAINER_ID:/home/publisher/ig/
        docker start -a $CONTAINER_ID
        EXIT_CODE=$?
        
        # Copy outputs
        echo "Copying outputs from container..."
        docker cp $CONTAINER_ID:/tmp/build/output ./output || echo "Warning: No output directory"
        docker cp $CONTAINER_ID:/tmp/build/fsh-generated ./fsh-generated || echo "No FSH generated"
        docker cp $CONTAINER_ID:/tmp/build/input-cache ./input-cache || echo "No input-cache"
        docker cp $CONTAINER_ID:/tmp/build/temp ./temp || echo "No temp directory"
        
        if [ $EXIT_CODE -ne 0 ]; then
          echo "Build failed, showing logs:"
          docker logs $CONTAINER_ID
          docker rm $CONTAINER_ID
          exit 1
        fi
        
        docker rm $CONTAINER_ID
        
        if [ ! -f "output/index.html" ]; then
          echo "ERROR: Build failed - no index.html"
          exit 1
        fi
        
        echo "✅ Build successful!"
    
    - name: Update package-list.json and package-feed.xml for releases
      if: steps.version.outputs.build_type == 'release'
      run: |
        VERSION="${{ steps.version.outputs.version }}"
        DATE=$(date +%Y-%m-%d)
        DATETIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
        
        # Update package-list.json and package-feed.xml
        cat > update-registry-files.py << 'EOF'
        import json
        import sys
        import xml.etree.ElementTree as ET
        from datetime import datetime
        
        version = sys.argv[1]
        date = sys.argv[2]
        datetime_iso = sys.argv[3]
        
        # ========== Update package-list.json ==========
        with open('package-list.json', 'r') as f:
            pkg_list = json.load(f)
        
        # Update current build path
        for entry in pkg_list['list']:
            if entry['version'] == 'current':
                entry['path'] = 'https://fhir.dghs.gov.bd/core/'
                break
        
        # Check if this version already exists
        version_exists = any(e['version'] == version for e in pkg_list['list'])
        
        if not version_exists:
            # Add new version entry
            new_entry = {
                "version": version,
                "date": date,
                "desc": f"Release {version}",
                "path": f"https://fhir.dghs.gov.bd/core/{version}/",
                "status": "trial-use",
                "sequence": "STU 1"
            }
            # Insert after 'current' entry
            pkg_list['list'].insert(1, new_entry)
        else:
            # Update existing entry
            for entry in pkg_list['list']:
                if entry['version'] == version:
                    entry['date'] = date
                    entry['path'] = f"https://fhir.dghs.gov.bd/core/{version}/"
                    break
        
        with open('output/package-list.json', 'w') as f:
            json.dump(pkg_list, f, indent=2)
        
        print(f"✅ Updated package-list.json with version {version}")
        
        # ========== Update package-feed.xml ==========
        # Register namespaces
        ET.register_namespace('', 'http://www.w3.org/2005/Atom')
        
        # Parse existing feed
        tree = ET.parse('package-feed.xml')
        root = tree.getroot()
        ns = {'atom': 'http://www.w3.org/2005/Atom'}
        
        # Update feed updated timestamp
        updated_elem = root.find('atom:updated', ns)
        if updated_elem is not None:
            updated_elem.text = datetime_iso
        
        # Check if entry for this version already exists
        entry_exists = False
        for entry in root.findall('atom:entry', ns):
            title = entry.find('atom:title', ns)
            if title is not None and version in title.text:
                entry_exists = True
                # Update existing entry timestamp
                entry_updated = entry.find('atom:updated', ns)
                if entry_updated is not None:
                    entry_updated.text = datetime_iso
                break
        
        # If entry doesn't exist, create new one
        if not entry_exists:
            new_entry = ET.Element('{http://www.w3.org/2005/Atom}entry')
            
            title = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}title')
            title.text = f"bd.fhir.core version {version}"
            
            link = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}link')
            link.set('rel', 'alternate')
            link.set('href', f"https://fhir.dghs.gov.bd/core/{version}/")
            
            entry_id = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}id')
            entry_id.text = f"https://fhir.dghs.gov.bd/core/{version}/"
            
            entry_updated = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}updated')
            entry_updated.text = datetime_iso
            
            summary = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}summary')
            summary.text = f"Release {version} of Bangladesh Core FHIR Implementation Guide"
            
            # Insert new entry at the beginning (after feed metadata)
            # Find the position after the last feed-level element
            insert_pos = 0
            for i, child in enumerate(root):
                if child.tag.endswith('entry'):
                    insert_pos = i
                    break
                insert_pos = i + 1
            
            root.insert(insert_pos, new_entry)
        
        # Write updated feed
        tree.write('output/package-feed.xml', encoding='utf-8', xml_declaration=True)
        print(f"✅ Updated package-feed.xml with version {version}")
        
        EOF
        
        python3 update-registry-files.py "$VERSION" "$DATE" "$DATETIME"
        
        # Copy updated files
        cp output/package-list.json package-list.json
        cp output/package-feed.xml package-feed.xml
        
        echo "📋 Updated registry files (package-list.json and package-feed.xml)"
    
    - name: Prepare deployment artifact
      run: |
        VERSION="${{ steps.version.outputs.version }}"
        BUILD_TYPE="${{ steps.version.outputs.build_type }}"
        
        # Create a tarball of the output
        if [ "$BUILD_TYPE" == "release" ]; then
          tar -czf ig-output.tar.gz -C output .
        else
          tar -czf ig-output.tar.gz -C output .
        fi
        
        echo "version=$VERSION" > deployment.env
        echo "build_type=$BUILD_TYPE" >> deployment.env
        echo "build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> deployment.env
        
        ls -lh ig-output.tar.gz
    
    - name: Upload artifact
      uses: actions/upload-artifact@v3
      with:
        name: ig-output
        path: |
          ig-output.tar.gz
          deployment.env
          package-list.json
          package-feed.xml
        retention-days: 30

  deploy:
    needs: build-ig
    runs-on: ubuntu-latest
    if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
    
    steps:
    - name: Download artifact
      uses: actions/download-artifact@v3
      with:
        name: ig-output
    
    - name: Load deployment env
      id: deploy_info
      run: |
        source deployment.env
        echo "version=$version" >> $GITHUB_OUTPUT
        echo "build_type=$build_type" >> $GITHUB_OUTPUT
        echo "build_date=$build_date" >> $GITHUB_OUTPUT
        
        echo "Deploying version: $version"
        echo "Build type: $build_type"
    
    - name: Deploy to server
      uses: appleboy/scp-action@v0.1.7
      with:
        host: ${{ secrets.DEPLOY_HOST }}
        username: ${{ secrets.DEPLOY_USER }}
        password: ${{ secrets.DEPLOY_PASSWORD }}
        port: ${{ secrets.DEPLOY_PORT || 22 }}
        source: "ig-output.tar.gz,deployment.env,package-list.json,package-feed.xml"
        target: "/tmp/fhir-ig-deploy/"
    
    - name: Execute deployment on server
      uses: appleboy/ssh-action@v1.0.3
      with:
        host: ${{ secrets.DEPLOY_HOST }}
        username: ${{ secrets.DEPLOY_USER }}
        password: ${{ secrets.DEPLOY_PASSWORD }}
        port: ${{ secrets.DEPLOY_PORT || 22 }}
        script: |
          set -e
          
          # Load deployment info
          source /tmp/fhir-ig-deploy/deployment.env
          
          echo "=========================================="
          echo "Deploying FHIR IG"
          echo "Version: $version"
          echo "Build Type: $build_type"
          echo "Build Date: $build_date"
          echo "=========================================="
          
          # Create version directory structure
          VERSIONS_DIR="/opt/fhir-ig/versions"
          mkdir -p "$VERSIONS_DIR"
          
          # Determine target directory
          if [ "$build_type" == "release" ]; then
            TARGET_DIR="$VERSIONS_DIR/$version"
            echo "📦 Deploying release version to: $TARGET_DIR"
          else
            TARGET_DIR="$VERSIONS_DIR/dev"
            echo "🔧 Deploying dev build to: $TARGET_DIR"
          fi
          
          # Create target directory
          mkdir -p "$TARGET_DIR"
          
          # Extract IG output
          echo "Extracting IG output..."
          tar -xzf /tmp/fhir-ig-deploy/ig-output.tar.gz -C "$TARGET_DIR"
          
          # Copy package-list.json to root
          cp /tmp/fhir-ig-deploy/package-list.json "$VERSIONS_DIR/package-list.json"
          
          # Copy package-feed.xml to root
          cp /tmp/fhir-ig-deploy/package-feed.xml "$VERSIONS_DIR/package-feed.xml"
          
          # Update 'current' symlink for releases
          if [ "$build_type" == "release" ]; then
            echo "Updating 'current' symlink to point to $version"
            rm -f "$VERSIONS_DIR/current"
            ln -sf "$version" "$VERSIONS_DIR/current"
          fi
          
          # Ensure nginx container is running with correct config
          cd /opt/fhir-ig
          
          # Download deployment files if they don't exist
          if [ ! -f "docker-compose.prod.yml" ]; then
            echo "ERROR: docker-compose.prod.yml not found!"
            echo "Please deploy the updated docker-compose.prod.yml and nginx.conf first"
            exit 1
          fi
          
          # Restart nginx to pick up new content
          docker compose -f docker-compose.prod.yml restart fhir-ig || \
            docker compose -f docker-compose.prod.yml up -d
          
          # Cleanup
          rm -rf /tmp/fhir-ig-deploy
          
          echo "=========================================="
          echo "✅ Deployment completed successfully!"
          echo "Version $version is now available at:"
          if [ "$build_type" == "release" ]; then
            echo "  - https://fhir.dghs.gov.bd/core/$version/"
            echo "  - https://fhir.dghs.gov.bd/core/ (current)"
          else
            echo "  - https://fhir.dghs.gov.bd/core/dev/"
          fi
          echo "=========================================="
          
          # List all versions
          echo "Available versions:"
          ls -lh "$VERSIONS_DIR" | grep -v total