name: CI

on:
  push:
    branches: [master, release/v1]
  pull_request:
    branches: [master, release/v1]
  merge_group:

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
      - uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: "1.26.4"

      - name: Install system dependencies
        if: runner.os == 'Linux'
        run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev

      - name: Tidy modules
        run: go mod tidy

      - name: Test
        run: go test -v ./...

      - name: Build
        run: go build -v ./...

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: "1.26.4"

      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev

      - name: Check formatting
        run: |
          unformatted=$(gofmt -l .)
          if [ -n "$unformatted" ]; then
            echo "::error::The following files are not formatted with gofmt:"
            echo "$unformatted"
            exit 1
          fi

      - name: Vet
        run: go vet ./...

      - name: golangci-lint
        uses: golangci/golangci-lint-action@v9
        with:
          version: v2.12.2
          args: --timeout=10m --build-tags=integration
          only-new-issues: false

  mod-tidy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: "1.26.4"

      - name: Check go.mod and go.sum are tidy
        run: |
          go mod tidy
          if ! git diff --quiet go.mod go.sum; then
            echo "::error::go.mod or go.sum are not tidy. Run 'go mod tidy' and commit the changes."
            git diff go.mod go.sum
            exit 1
          fi

  website:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: docs
    steps:
      - uses: actions/checkout@v6

      - name: Set up Node.js
        uses: actions/setup-node@v6
        with:
          node-version: "24"
          cache: npm
          cache-dependency-path: docs/package-lock.json

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npx docusaurus build

  snap:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Validate snapcraft.yaml
        run: |
          sudo snap install snapcraft --classic
          # Verify snapcraft can parse the project file
          snapcraft list-plugins
          # Validate YAML structure and required fields
          python3 << 'PYEOF'
          import yaml, sys

          with open("snapcraft.yaml") as f:
              snap = yaml.safe_load(f)

          errors = []
          for field in ("name", "base", "summary", "description", "parts"):
              if field not in snap:
                  errors.append(f"Missing required field: {field}")

          if "apps" in snap:
              for app_name, app in snap["apps"].items():
                  if "command" not in app:
                      errors.append(f"App '{app_name}' missing 'command'")

          if "parts" in snap:
              for part_name, part in snap["parts"].items():
                  if "plugin" not in part and "override-build" not in part:
                      errors.append(f"Part '{part_name}' missing 'plugin' or 'override-build'")

          if errors:
              for e in errors:
                  print(f"::error::{e}", file=sys.stderr)
              sys.exit(1)

          print("snapcraft.yaml is valid.")
          PYEOF

  flatpak:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y python3-pip
          pip3 install PyYAML

      - name: Validate Flatpak manifest YAML
        run: python3 -c "import yaml, sys; yaml.safe_load(open('com.floatpane.matcha.yaml'))"

      - name: Check Flatpak manifest structure
        run: |
          python3 << 'EOF'
          import yaml, sys

          with open("com.floatpane.matcha.yaml") as f:
              manifest = yaml.safe_load(f)

          errors = []
          for field in ("id", "runtime", "runtime-version", "sdk", "command", "modules"):
              if field not in manifest:
                  errors.append(f"Missing required field: {field}")

          if "modules" in manifest:
              for mod in manifest["modules"]:
                  if "name" not in mod:
                      errors.append(f"Module missing 'name' field: {mod}")
                  if "sources" not in mod and "buildsystem" not in mod:
                      errors.append(f"Module '{mod.get('name', '?')}' missing 'sources' or 'buildsystem'")

          if errors:
              for e in errors:
                  print(f"::error::{e}", file=sys.stderr)
              sys.exit(1)

          print("Flatpak manifest is valid.")
          EOF

  nix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Nix
        uses: cachix/install-nix-action@v31
        with:
          nix_path: nixpkgs=channel:nixpkgs-unstable

      - name: Check flake
        run: nix flake check --no-build

  lua-plugins:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Lua
        run: sudo apt-get update && sudo apt-get install -y lua5.4

      - name: Check Lua syntax
        run: |
          failed=0
          for f in plugins/*.lua; do
            if ! luac -p "$f" 2>&1; then
              echo "::error file=$f::Syntax error in $f"
              failed=1
            fi
          done
          exit $failed

  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: "1.26.4"

      - name: Install GoReleaser
        uses: goreleaser/goreleaser-action@v7
        with:
          install-only: true

      - name: Validate release config
        run: goreleaser check -f .goreleaser.yml

      - name: Validate nightly config
        run: goreleaser check -f .goreleaser.nightly.yml
