name: CI/CD Pipeline

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

env:
  PYTHON_VERSION: "3.10"
  POETRY_VERSION: "1.7.0"

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12"]

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

    - name: Set up Python {% raw %}${{ matrix.python-version }}{% endraw %}
      uses: actions/setup-python@v4
      with:
        python-version: {% raw %}${{ matrix.python-version }}{% endraw %}

    - name: Install Poetry
      uses: snok/install-poetry@v1
      with:
        version: {% raw %}${{ env.POETRY_VERSION }}{% endraw %}
        virtualenvs-create: true
        virtualenvs-in-project: true

    - name: Load cached venv
      id: cached-poetry-dependencies
      uses: actions/cache@v3
      with:
        path: .venv
        key: venv-{% raw %}${{ runner.os }}{% endraw %}-{% raw %}${{ matrix.python-version }}{% endraw %}-{% raw %}${{ hashFiles('**/poetry.lock') }}{% endraw %}

    - name: Install dependencies
      if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
      run: poetry install --no-interaction --no-root

    - name: Run tests
      run: |
        poetry run pytest --cov=. --cov-report=xml --cov-report=html
        poetry run pytest --cov=. --cov-report=term-missing

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml
        flags: unittests
        name: codecov-umbrella
        fail_ci_if_error: false

  lint:
    runs-on: ubuntu-latest

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

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: {% raw %}${{ env.PYTHON_VERSION }}{% endraw %}

    - name: Install Poetry
      uses: snok/install-poetry@v1
      with:
        version: {% raw %}${{ env.POETRY_VERSION }}{% endraw %}

    - name: Install dependencies
      run: poetry install --no-interaction --no-root

    - name: Run Black
      run: poetry run black --check --diff .

    - name: Run Ruff
      run: poetry run ruff check .

    - name: Run isort
      run: poetry run isort --check-only --diff .

    - name: Run Flake8
      run: poetry run flake8 .

  security:
    runs-on: ubuntu-latest

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

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: {% raw %}${{ env.PYTHON_VERSION }}{% endraw %}

    - name: Install Poetry
      uses: snok/install-poetry@v1
      with:
        version: {% raw %}${{ env.POETRY_VERSION }}{% endraw %}

    - name: Install dependencies
      run: poetry install --no-interaction --no-root

    - name: Run Bandit security scan
      run: poetry run bandit -r . -f json -o bandit-report.json || true

    - name: Run Safety dependency check
      run: poetry run safety check --json --output safety-report.json || true

    - name: Upload security reports
      uses: actions/upload-artifact@v3
      with:
        name: security-reports
        path: |
          bandit-report.json
          safety-report.json

  build:
    needs: [test, lint, security]
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'

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

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Build Docker image
      run: docker build -t {{ project_name }}:latest .

    - name: Run container tests
      run: |
        docker run --rm {{ project_name }}:latest python -m pytest --version
        docker run --rm {{ project_name }}:latest python -c "import fastapi; print('FastAPI version:', fastapi.__version__)"

  deploy-dev:
    needs: build
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
    environment: development

    steps:
    - name: Deploy to development
      run: echo "Deploying to development environment"
      # Add your deployment logic here

  deploy-staging:
    needs: build
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    environment: staging

    steps:
    - name: Deploy to staging
      run: echo "Deploying to staging environment"
      # Add your deployment logic here

  deploy-prod:
    needs: build
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    environment: production

    steps:
    - name: Deploy to production
      run: echo "Deploying to production environment"
      # Add your deployment logic here
