name: Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: "Version to release (vX.Y.Z format)"
        required: true
        default: "v0.1.0"
      prerelease:
        description: "Is this a pre-release?"
        type: boolean
        default: false
  push:
    tags:
      - "v*"

# Restrict top-level permissions to minimum required defaults
permissions: read-all

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  prepare:
    name: Prepare Release
    runs-on: ubuntu-latest
    # Only prepare job needs write permissions for commit and tagging
    permissions:
      contents: write # Required for git auto-commit
    outputs:
      version: ${{ steps.get-version.outputs.version }}
      npm_version: ${{ steps.get-version.outputs.npm_version }}
      is_prerelease: ${{ github.event.inputs.prerelease || 'false' }}
    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit

      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.3.1
        with:
          fetch-depth: 0

      - name: Get version
        id: get-version
        run: |
          if [[ "${{ github.event_name }}" == "push" ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
          else
            VERSION=${{ github.event.inputs.version }}
          fi
          echo "version=${VERSION}" >> $GITHUB_OUTPUT
          # npm version without 'v' prefix
          NPM_VERSION="${VERSION#v}"
          echo "npm_version=${NPM_VERSION}" >> $GITHUB_OUTPUT
          echo "Version: ${VERSION}"
          echo "npm version: ${NPM_VERSION}"

      - name: Setup Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: "25"
          cache: "npm"

      - name: Cache dependencies
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm ci

      - name: Build TypeScript
        run: npm run build

      - name: Run linter
        run: npm run lint

      - name: Validate HTML
        run: npm run htmlhint || echo "HTML validation completed"

      - name: Set Version for release
        if: github.event_name == 'workflow_dispatch'
        run: |
          PLAIN_VERSION="${{ github.event.inputs.version }}"
          # Remove 'v' prefix if present
          PLAIN_VERSION="${PLAIN_VERSION#v}"
          npm version $PLAIN_VERSION --no-git-tag-version

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Run tests with coverage
        run: npm run test:coverage

      - name: Generate lint reports
        run: |
          echo "🔍 Generating ESLint reports..."
          mkdir -p builds/test-results
          npm run lint:report || true
          npm run lint:report:html || true

      - name: Run E2E tests
        run: npm run test:e2e

      - name: Clean old documentation
        run: |
          echo "🧹 Cleaning old documentation..."
          rm -rf docs/api docs/coverage docs/test-results docs/playwright-report

      - name: Generate API documentation
        run: |
          echo "📖 Generating API documentation..."
          npm run docs:api

      - name: Copy test reports to docs
        run: |
          echo "📋 Copying test reports..."
          npm run docs:copy-reports

      - name: Generate documentation index
        run: |
          echo "📚 Generating documentation index..."
          npm run docs:index

      - name: Verify documentation structure
        run: |
          echo "🔍 Verifying documentation structure..."
          
          # Check required directories exist
          for dir in docs/api docs/coverage docs/test-results docs/playwright-report; do
            if [ -d "$dir" ]; then
              echo "✅ $dir exists"
            else
              echo "❌ $dir missing"
              exit 1
            fi
          done
          
          # Check required files exist
          for file in docs/index.html docs/api/index.html docs/coverage/index.html docs/playwright-report/index.html docs/test-results/index.html; do
            if [ -f "$file" ]; then
              echo "✅ $file exists"
            else
              echo "❌ $file missing"
              exit 1
            fi
          done
          
          # Check optional but expected report files
          for file in docs/test-results/results.json docs/test-results/junit.xml docs/test-results/eslint-report.html docs/test-results/eslint-report.json; do
            if [ -f "$file" ]; then
              echo "✅ $file exists"
            else
              echo "⚠️  $file not found (optional)"
            fi
          done
          
          # Check vitest HTML report directory
          if [ -d "docs/test-results/html" ]; then
            echo "✅ docs/test-results/html exists (Vitest HTML report)"
          else
            echo "⚠️  docs/test-results/html not found (optional)"
          fi
          
          echo "✅ Documentation structure validated"

      - name: Commit documentation updates
        uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
        with:
          commit_message: "docs: update documentation for ${{ steps.get-version.outputs.version }}"
          file_pattern: "docs/**/*"
          skip_fetch: false
          skip_checkout: false

      - name: Create version tag
        if: github.event_name == 'workflow_dispatch'
        uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
        with:
          commit_message: "chore(release): bump version to ${{ github.event.inputs.version }}"
          tagging_message: "${{ github.event.inputs.version }}"

  build:
    name: Build Release Package
    needs: [prepare]
    runs-on: ubuntu-latest
    # Build job needs specific permissions for attestations
    permissions:
      contents: read
      id-token: write # Required for OIDC
      attestations: write # Required for SBOM and build attestations
    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit

      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.3.1
        with:
          fetch-depth: 0
          # Use GITHUB_REF directly for tag events
          ref: ${{ github.event_name == 'push' && github.ref || github.event_name == 'workflow_dispatch' && github.event.inputs.version || '' }}

      - name: Setup Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: "25"
          cache: "npm"

      - name: Cache dependencies
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm ci

      - name: Build TypeScript
        run: npm run build

      - name: Generate sample news (if needed)
        run: |
          # Generate static content (sitemap, political-intelligence pages)
          echo "📰 Generating static content..."
          npm run prebuild || echo "Prebuild skipped"
          npm run generate-news-indexes || echo "Index generation skipped"

      - name: Create release artifacts
        run: |
          # Create the zip file from the repository
          mkdir -p release-artifacts
          
          # Include all necessary files including documentation
          zip -r release-artifacts/euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip \
            news/ \
            docs/ \
            scripts/ \
            styles.css \
            index-*.html \
            sitemap.xml \
            package.json \
            package-lock.json \
            README.md \
            LICENSE \
            -x "*.git*" "node_modules/*"

      - name: Upload build artifact
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v6.0.0
        with:
          name: build-artifacts
          path: release-artifacts/
          if-no-files-found: error

      - name: Generate SBOM
        uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
        id: sbom
        with:
          format: spdx-json
          output-file: euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json
          artifact-name: euparliamentmonitor-${{ needs.prepare.outputs.version }}

      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
        id: attest
        with:
          subject-path: release-artifacts/euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip

      - name: Copy artifact attestation for zip
        run: cp ${{ steps.attest.outputs.bundle-path }} euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip.intoto.jsonl

      - name: Generate SBOM attestation
        id: attestsbom
        uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
        with:
          subject-path: release-artifacts/euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip
          sbom-path: euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json

      - name: Copy SBOM attestation for zip
        run: cp ${{ steps.attestsbom.outputs.bundle-path }} euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json.intoto.jsonl

      - name: Upload security artifacts
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v6.0.0
        with:
          name: security-artifacts
          path: |
            euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json
            euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip.intoto.jsonl
            euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json.intoto.jsonl
          if-no-files-found: error

  release:
    name: Create Release
    needs: [prepare, build]
    runs-on: ubuntu-latest
    # Release job needs specific permissions to create GitHub releases
    permissions:
      contents: write # Required to create releases
      id-token: write # Required for OIDC
    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit

      # Checkout main branch to get latest documentation
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.3.1
        with:
          fetch-depth: 0
          ref: main # Always use main branch for deployment

      - name: Download build artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: build-artifacts
          path: artifacts/build

      - name: Download security artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: security-artifacts
          path: artifacts/security

      - name: Draft Release Notes
        id: release-drafter
        uses: release-drafter/release-drafter@5de93583980a40bd78603b6dfdcda5b4df377b32 # v7.2.0
        with:
          version: ${{ needs.prepare.outputs.version }}
          tag: ${{ needs.prepare.outputs.version }}
          name: EU Parliament Monitor ${{ needs.prepare.outputs.version }}
          publish: false
          prerelease: ${{ needs.prepare.outputs.is_prerelease }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Create GitHub Release with all artifacts
      - name: Create GitHub Release
        uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
        with:
          tag: ${{ needs.prepare.outputs.version }}
          name: EU Parliament Monitor ${{ needs.prepare.outputs.version }}
          body: |
            ${{ steps.release-drafter.outputs.body }}

            ## 📦 Release Artifacts

            - `euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip` - Full application package
            - `euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json` - SBOM (Software Bill of Materials)
            - `*.intoto.jsonl` - SLSA Build Provenance Attestations

            ## 📦 npm Package

            ```bash
            npm install euparliamentmonitor@${{ needs.prepare.outputs.npm_version }}
            ```

            Published with [npm provenance](https://docs.npmjs.com/generating-provenance-statements) for supply chain security.

            ## 📚 Documentation

            - [API Documentation](https://hack23.github.io/euparliamentmonitor/docs/api/)
            - [Test Coverage Report](https://hack23.github.io/euparliamentmonitor/docs/coverage/)
            - [E2E Test Report](https://hack23.github.io/euparliamentmonitor/docs/playwright-report/)
            - [Documentation Hub](https://hack23.github.io/euparliamentmonitor/docs/)

            ## 🔐 Security

            All artifacts include SLSA Build Provenance attestations and SBOM for supply chain security.
            Verify attestations using the GitHub CLI:

            ```bash
            gh attestation verify euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip -R Hack23/euparliamentmonitor
            ```
          generateReleaseNotes: false
          immutableCreate: true
          draft: false
          prerelease: ${{ needs.prepare.outputs.is_prerelease }}
          artifacts: |
            artifacts/build/euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip
            artifacts/security/euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json
            artifacts/security/euparliamentmonitor-${{ needs.prepare.outputs.version }}.zip.intoto.jsonl
            artifacts/security/euparliamentmonitor-${{ needs.prepare.outputs.version }}.spdx.json.intoto.jsonl
          token: ${{ secrets.GITHUB_TOKEN }}

      # ─── npm Publish ────────────────────────────────────────────────────
      - name: Checkout release tag for npm publish
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.3.1
        with:
          ref: ${{ needs.prepare.outputs.version }}

      - name: Setup Node.js for npm publish
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: "25"
          cache: "npm"
          registry-url: "https://registry.npmjs.org"

      - name: Cache dependencies
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm ci

      - name: Build package
        run: npm run build

      - name: Verify package contents
        run: |
          echo "📦 Package contents preview:"
          npm pack --dry-run
          echo ""
          echo "📋 Package entry point:"
          node --input-type=module -e "
            import { readFileSync } from 'fs';
            const pkg = JSON.parse(readFileSync('./package.json', 'utf8'));
            console.log('main:', pkg.main);
            console.log('types:', pkg.types);
            console.log('exports:', JSON.stringify(pkg.exports, null, 2));
          "

      - name: Publish to npm with provenance
        run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          NPM_CONFIG_PROVENANCE: true

      - name: Verify npm package
        run: |
          echo "✅ Package published successfully!"
          echo "📦 Package: euparliamentmonitor@${{ needs.prepare.outputs.npm_version }}"
          echo "🔗 npm URL: https://www.npmjs.com/package/euparliamentmonitor"
          echo ""
          echo "To install:"
          echo "  npm install euparliamentmonitor@${{ needs.prepare.outputs.npm_version }}"
          echo ""
          echo "To verify provenance:"
          echo "  npm audit signatures"
