name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgis/postgis:16-3.4-alpine
        env:
          POSTGRES_DB: roadwave_test
          POSTGRES_USER: roadwave
          POSTGRES_PASSWORD: test_password
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

      redis:
        image: redis:7-alpine
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Cache Go modules
        uses: actions/cache@v3
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-

      - name: Install dependencies
        run: |
          go mod download
          go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
          go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest

      - name: Generate sqlc code
        run: sqlc generate

      - name: Run migrations
        env:
          DATABASE_URL: postgres://roadwave:test_password@localhost:5432/roadwave_test?sslmode=disable
        run: migrate -path migrations -database "$DATABASE_URL" up

      - name: Run unit tests
        run: go test -v -race -short -coverprofile=coverage.out ./...

      - name: Run BDD tests
        run: |
          go install github.com/cucumber/godog/cmd/godog@latest
          godog run features/

      - name: Check coverage
        run: |
          coverage=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//')
          echo "Total coverage: $coverage%"
          if (( $(echo "$coverage < 80" | bc -l) )); then
            echo "❌ Coverage $coverage% is below 80%"
            exit 1
          fi

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage.out
          flags: unittests
          name: codecov-umbrella

  lint:
    name: Lint
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Run golangci-lint
        uses: golangci/golangci-lint-action@v4
        with:
          version: latest
          args: --timeout=5m

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [test, lint]

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Build binary
        run: |
          CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o bin/api ./cmd/api

      - name: Build Docker image
        run: docker build -f docker/Dockerfile -t roadwave:${{ github.sha }} .

      - name: Log in to Docker registry (main branch only)
        if: github.ref == 'refs/heads/main'
        run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin

      - name: Push Docker image (main branch only)
        if: github.ref == 'refs/heads/main'
        run: |
          docker tag roadwave:${{ github.sha }} ${{ secrets.DOCKER_REGISTRY }}/roadwave:latest
          docker tag roadwave:${{ github.sha }} ${{ secrets.DOCKER_REGISTRY }}/roadwave:${{ github.sha }}
          docker push ${{ secrets.DOCKER_REGISTRY }}/roadwave:latest
          docker push ${{ secrets.DOCKER_REGISTRY }}/roadwave:${{ github.sha }}
