name: FHIR IG CI/CD Pipeline with Version Persistence

on:
  push:
    tags:
      - 'v*.*.*'
  pull_request:
    branches: [ main ]

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

jobs:
  build-ig:
    runs-on: fhir-runner

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Extract version from IG
        id: version
        run: |
          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

          if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
            BUILD_TYPE="release"
            TAG_VERSION="${GITHUB_REF#refs/tags/v}"

            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: Prepare package-list.json and history.xml for IG Publisher
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          BUILD_TYPE="${{ steps.version.outputs.build_type }}"
          DATE=$(date +%Y-%m-%d)

          export VERSION DATE BUILD_TYPE

          echo "📋 Preparing package-list.json and history.xml for IG Publisher..."

          if [ ! -f "package-list.json" ]; then
            echo "⚠️ package-list.json not found in repo root"
            echo "Creating initial package-list.json..."
            cat > package-list.json << 'PKGEOF'
          {
            "package-id": "bd.fhir.core",
            "title": "Bangladesh Core FHIR Implementation Guide",
            "canonical": "https://fhir.dghs.gov.bd/core",
            "introduction": "The Bangladesh Core FHIR IG defines national base profiles, value sets, and extensions for health data interoperability.",
            "list": [
              {
                "version": "current",
                "desc": "Continuous Integration Build (latest in version control)",
                "path": "https://fhir.dghs.gov.bd/core/",
                "status": "ci-build",
                "current": true
              }
            ]
          }
          PKGEOF
          fi

          python3 << 'PYEOF'
          import json
          import os
          import sys

          version = os.environ.get('VERSION', '')
          date = os.environ.get('DATE', '')
          build_type = os.environ.get('BUILD_TYPE', '')

          with open('package-list.json', 'r', encoding='utf-8') as f:
              pkg_list = json.load(f)

          if 'list' not in pkg_list or not isinstance(pkg_list['list'], list):
              print("ERROR: package-list.json does not contain a valid 'list' array")
              sys.exit(1)

          current_entries = [e for e in pkg_list['list'] if e.get('version') == 'current']
          if not current_entries:
              pkg_list['list'].insert(0, {
                  "version": "current",
                  "desc": "Continuous Integration Build (latest in version control)",
                  "path": "https://fhir.dghs.gov.bd/core/",
                  "status": "ci-build",
                  "current": True
              })

          if build_type == 'release':
              version_entry = None
              for e in pkg_list['list']:
                  if e.get('version') == version:
                      version_entry = e
                      break
              if version_entry is None:
                  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_index = 1
                  for i, entry in enumerate(pkg_list['list']):
                      if entry.get('version') == 'current':
                          insert_index = i + 1
                          break

                  pkg_list['list'].insert(insert_index, new_entry)
                  print(f"✅ Added version {version} to package-list.json")
              else:
                  print(f"ℹ️ Version {version} already exists in package-list.json")
          else:
              print("ℹ️ Dev build - using existing package-list.json without release modification")

          with open('package-list.json', 'w', encoding='utf-8') as f:
              json.dump(pkg_list, f, indent=2, ensure_ascii=False)
          PYEOF

          echo "🔍 Validating package-list.json..."
          python3 -m json.tool package-list.json > /dev/null && echo "✅ Valid JSON" || (echo "❌ Invalid JSON!" && exit 1)

          echo "📂 Ensuring package-list.json is in required locations..."
          mkdir -p input
          cp package-list.json input/package-list.json

          echo "📝 Generating static history.xml from package-list.json..."
          mkdir -p input/pagecontent

          python3 << 'PYEOF'
          import json
          import os
          from html import escape

          os.makedirs('input/pagecontent', exist_ok=True)

          with open('package-list.json', 'r', encoding='utf-8') as f:
              pkg_list = json.load(f)

          xml = '''<?xml version="1.0" encoding="UTF-8"?>
          <div xmlns="http://www.w3.org/1999/xhtml">

          <p>This page provides the version history for the Bangladesh Core FHIR Implementation Guide.</p>

          <p>For a machine-readable version history see <a href="package-list.json">package-list.json</a>.</p>

          <p><b>Published Versions</b></p>

          <table class="grid table table-striped table-bordered table-hover">
          <thead>
          <tr>
          <th>Version</th>
          <th>Date</th>
          <th>Status</th>
          <th>Description</th>
          </tr>
          </thead>
          <tbody>
          '''

          def version_key(v):
              try:
                  return tuple(int(x) for x in v.split('.'))
              except:
                  return (0,)

          published = [
              e for e in pkg_list['list']
              if e.get('version') and e.get('version') != "current"
          ]

          # Sort newest version first
          published.sort(
              key=lambda e: version_key(e.get("version", "0.0.0")),
              reverse=True
          )

          published_found = False
          first_row = True

          for entry in published:
              published_found = True

              version = escape(entry.get('version', 'Unknown'))
              date = escape(entry.get('date', 'N/A'))
              desc = escape(entry.get('desc', ''))
              path = escape(entry.get('path', '#'))

              status_val = entry.get('status', 'unknown')

              if status_val == "trial-use":
                  status = '<span class="badge bg-info">Trial Use</span>'
              elif status_val == "normative":
                  status = '<span class="badge bg-success">Normative</span>'
              else:
                  status = f'<span class="badge bg-secondary">{escape(status_val)}</span>'

              badge = '<span class="badge bg-success">Latest</span> ' if first_row else ''

              xml += f'''
          <tr>
          <td><a href="{path}">{badge}{version}</a></td>
          <td>{date}</td>
          <td>{status}</td>
          <td>{desc}</td>
          </tr>
          '''

              first_row = False

          if not published_found:
              xml += '''
          <tr>
          <td colspan="4">No published versions available yet.</td>
          </tr>
          '''

          xml += '''
          </tbody>
          </table>

          <p class="lead"><b>Continuous Integration Build</b></p>
          '''

          current_entry = None
          for entry in pkg_list['list']:
              if entry.get('version') == 'current':
                  current_entry = entry
                  break

          if current_entry:
              path = escape(current_entry.get('path', pkg_list.get('canonical', '') + '/'))
              xml += f'''
          <p>The latest development build is available at:
          <a href="{path}">{path}</a></p>
          '''
          else:
              xml += '''
          <p><i>No CI build entry found in package-list.json.</i></p>
          '''

          xml += '''
          </div>
          '''

          with open('input/pagecontent/history.xml', 'w', encoding='utf-8') as f:
              f.write(xml)

          print("✅ Generated static history.xml")
          print(f"   File location: {os.path.abspath('input/pagecontent/history.xml')}")
          print(f"   File size: {os.path.getsize('input/pagecontent/history.xml')} bytes")
          PYEOF

          if [ -f "input/pagecontent/history.xml" ]; then
            echo "✅ Verified: history.xml exists"
            echo "   First 20 lines:"
            head -20 input/pagecontent/history.xml
          else
            echo "❌ ERROR: history.xml was not created!"
            exit 1
          fi

          echo "✅ Pre-build preparation complete:"
          echo "  - Root: $(pwd)/package-list.json"
          echo "  - Input: $(pwd)/input/package-list.json"
          echo "  - History: $(pwd)/input/pagecontent/history.xml"
          echo "==============================="
          echo "PACKAGE LIST USED FOR BUILD:"
          cat package-list.json
          echo "-------------------------------"
          echo "INPUT COPY:"
          cat input/package-list.json
          echo "==============================="

      - name: Emergency Disk Cleanup
        run: |
          echo "Disk usage before:"
          df -h

          echo "Clearing tool cache..."
          rm -rf /opt/hostedtoolcache/* || true

          rm -rf /usr/share/dotnet || true
          rm -rf /usr/local/lib/android || true
          rm -rf /opt/ghc || true
          rm -rf ~/.fhir/packages || true

          echo "Disk usage after:"
          df -h

      - name: Install Docker CLI
        run: |
          apt-get update
          apt-get install -y docker.io
          docker --version

      - name: Preload previous IG package for comparison
        run: |
          echo "Detecting previous version..."
          export VERSION="${{ steps.version.outputs.version }}"
          PREV_VERSION=$(python3 <<'PY'
          import json
          import os

          current_build = os.environ.get("VERSION")

          with open("package-list.json") as f:
              data = json.load(f)

          def parse(v):
              try:
                  return tuple(int(x) for x in v.split("."))
              except:
                  return (0,)

          versions = [
              v["version"]
              for v in data["list"]
              if v.get("version") not in ("current", current_build)
          ]

          versions.sort(key=parse, reverse=True)

          print(versions[0] if versions else "")
          PY
          )

              if [ -z "$PREV_VERSION" ]; then
                echo "No previous version found. Skipping preload."
                exit 0
              fi

              echo "Previous version detected: $PREV_VERSION"

          mkdir -p previous-packages
          TMPDIR=$(mktemp -d)

          URL="https://fhir.dghs.gov.bd/core/$PREV_VERSION/package.tgz"

          echo "Downloading $URL"
          curl -fL "$URL" -o "$TMPDIR/package.tgz"

          mkdir -p "previous-packages/bd.fhir.core#$PREV_VERSION"
          tar -xzf "$TMPDIR/package.tgz" --strip-components=1 -C "previous-packages/bd.fhir.core#$PREV_VERSION"

          echo "Previous package cached:"
          ls previous-packages

      - name: Build FHIR IG
        run: |
          echo "Building FHIR IG version ${{ steps.version.outputs.version }}..."
          PREV_VERSION=$(ls previous-packages/ 2>/dev/null | grep 'bd.fhir.core#' | sed 's/bd.fhir.core#//' | head -1)

          echo "Injecting previous version into ig.ini: $PREV_VERSION"
          if [ -n "$PREV_VERSION" ]; then
            if grep -q "^previous-version" ig.ini; then
              sed -i "s/^previous-version.*/previous-version = $PREV_VERSION/" ig.ini
            else
              # Ensure newline before appending
              echo "" >> ig.ini
              echo "previous-version = $PREV_VERSION" >> ig.ini
            fi
          fi
          
          cat ig.ini

          CONTAINER_ID=$(docker create \
            -v $(pwd)/previous-packages:/previous-packages \
            hl7fhir/ig-publisher-base:latest \
            /bin/bash -c "
            mkdir -p /tmp/build
            cp -r /home/publisher/ig /tmp/build/ig
            cd /tmp/build/ig
            mkdir -p input-cache
            curl -L -o input-cache/publisher.jar https://supervision.dghs.gov.bd/publisher.jar
            ls -lh input-cache
            rm -f package-list.json
            
            # NEW: Install previous packages to cache
            if [ -d /previous-packages ]; then
              echo 'Installing previous versions to package cache...'
              for pkg_dir in /previous-packages/bd.fhir.core#*; do
                if [ -d \"\$pkg_dir\" ]; then
                  PKG_NAME=\$(basename \"\$pkg_dir\")
                  echo \"  Installing \$PKG_NAME\"
                  cp -r \"\$pkg_dir\" /home/publisher/.fhir/packages/\$PKG_NAME
                fi
              done
              echo 'Previous versions installed'
            fi
            
            _genonce.sh
            ")

          echo "Container ID: $CONTAINER_ID"
          docker cp "$(pwd)/." "$CONTAINER_ID:/home/publisher/ig/"
          echo "Mounted FHIR packages:"
          ls -R previous-packages || echo "No previous packages directory"
          docker start -a "$CONTAINER_ID"
          EXIT_CODE=$?

          echo "Copying outputs from container..."
          docker cp "$CONTAINER_ID:/tmp/build/ig/output" ./output || echo "Warning: No output directory"
          docker cp "$CONTAINER_ID:/tmp/build/ig/fsh-generated" ./fsh-generated || echo "No FSH generated"
          docker cp "$CONTAINER_ID:/tmp/build/ig/input-cache" ./input-cache || echo "No input-cache"
          docker cp "$CONTAINER_ID:/tmp/build/ig/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 ""
          echo "🔍 Checking for history.html..."
          if [ -f "output/history.html" ]; then
            echo "✅ history.html generated successfully!"
            echo "📄 history.html size: $(ls -lh output/history.html | awk '{print $5}')"
          else
            echo "⚠️ WARNING: history.html was NOT generated"
            echo "This might indicate an issue with the template or history.xml/package-list.json"
          fi
          echo "================================"
          echo "IG Publisher comparison log:"
          cat output/qa.compare.txt || echo "qa.compare.txt not found"
          echo "================================"
          echo "✅ Build successful!"

      - name: Update package-feed.xml for releases
        if: steps.version.outputs.build_type == 'release'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          DATETIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)

          if [ ! -f "package-feed.xml" ]; then
            echo "⚠️ package-feed.xml not found, creating initial feed..."

            cat > package-feed.xml <<EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <feed xmlns="http://www.w3.org/2005/Atom">
            <title>bd.fhir.core</title>
            <id>https://fhir.dghs.gov.bd/core/package-feed.xml</id>
            <updated>$DATETIME</updated>
          </feed>
          EOF
              fi

              cat > update-feed.py << 'EOF'
          import sys
          import xml.etree.ElementTree as ET

          version = sys.argv[1]
          datetime_iso = sys.argv[2]

          ET.register_namespace('', 'http://www.w3.org/2005/Atom')

          tree = ET.parse('package-feed.xml')
          root = tree.getroot()
          ns = {'atom': 'http://www.w3.org/2005/Atom'}

          updated_elem = root.find('atom:updated', ns)
          if updated_elem is not None:
              updated_elem.text = datetime_iso

          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 or ''):
                  entry_exists = True
                  entry_updated = entry.find('atom:updated', ns)
                  if entry_updated is not None:
                      entry_updated.text = datetime_iso
                  break

          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_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)

          tree.write('output/package-feed.xml', encoding='utf-8', xml_declaration=True)
          print("✅ Updated package-feed.xml")
          EOF

              python3 update-feed.py "$VERSION" "$DATETIME"

              cp package-list.json output/package-list.json

              echo "📋 Updated registry files"

      - name: Prepare deployment artifact
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          BUILD_TYPE="${{ steps.version.outputs.build_type }}"

          tar -czf ig-output.tar.gz -C output .

          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

          echo "📦 Output contents:"
          ls -lh output/ | grep -E "(history\.html|package-list\.json|package-feed\.xml|index\.html)" || echo "Some files may be missing"

          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

            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 "=========================================="

            VERSIONS_DIR="/opt/fhir-ig/versions"
            mkdir -p "$VERSIONS_DIR"

            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"
              mkdir -p "$TARGET_DIR"
              echo "Cleaning old dev files..."
              rm -rf "$TARGET_DIR"/*
            fi

            mkdir -p "$TARGET_DIR"

            echo "Extracting IG output..."
            tar -xzf /tmp/fhir-ig-deploy/ig-output.tar.gz -C "$TARGET_DIR"

            if [ -f "$TARGET_DIR/history.html" ]; then
              echo "✅ history.html deployed successfully"
            else
              echo "⚠️ WARNING: history.html not found in deployment"
            fi

            cp "$TARGET_DIR/package-list.json" "$VERSIONS_DIR/package-list.json"
            cp "$TARGET_DIR/package-feed.xml" "$VERSIONS_DIR/package-feed.xml"

            cp "$TARGET_DIR/package-list.json" "/opt/fhir-ig/package-list.json"
            cp "$TARGET_DIR/package-feed.xml" "/opt/fhir-ig/package-feed.xml"

            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

            cd /opt/fhir-ig

            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

            docker compose -f docker-compose.prod.yml up -d --force-recreate fhir-ig

            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/$version/history.html"
              echo "  - https://fhir.dghs.gov.bd/core/ (current)"
            else
              echo "  - https://fhir.dghs.gov.bd/core/dev/"
            fi
            echo "=========================================="

            echo "Available versions:"
            ls -lh "$VERSIONS_DIR" | grep -v total