apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: web-app-deployment
  title: Web Application Deployment
  description: Deploy a web application from container image or Git repository with S2I
  tags:
    - web-app
    - kubernetes
    - s2i
    - paid
    - flexible
  annotations:
    backstage.io/pricing-tier: basic
    backstage.io/base-cost: "15"
    backstage.io/cost-calculation: dynamic
spec:
  owner: platform-team
  type: service
  
  parameters:
    - title: Application Information
      required:
        - name
        - description
        - owner
        - deploymentType
      properties:
        name:
          title: Application Name
          type: string
          description: Unique name for your application
          pattern: '^[a-z0-9-]+$'
          maxLength: 30
        description:
          title: Description
          type: string
          description: Brief description of your application
        owner:
          title: Owner
          type: string
          description: Owner of the application
          ui:field: OwnerPicker
          ui:options:
            catalogFilter:
              kind: [Group, User]
        
        deploymentType:
          title: Deployment Type
          type: string
          description: How do you want to deploy your application?
          enum:
            - container
            - git-s2i
          enumNames:
            - Container Image
            - Git Repository (Source-to-Image)
    
    - title: Container Configuration
      when:
        properties:
          deploymentType:
            const: container
      required:
        - containerImage
      properties:
        containerImage:
          title: Container Image
          type: string
          description: Full container image path (e.g., nginx:latest, quay.io/my-org/my-app:v1.0.0)
          placeholder: nginx:latest
        
        containerPort:
          title: Container Port
          type: integer
          description: Port that your application listens on
          default: 8080
          minimum: 1
          maximum: 65535
    
    - title: Git Repository Configuration
      when:
        properties:
          deploymentType:
            const: git-s2i
      required:
        - gitRepository
        - buildStrategy
      properties:
        gitRepository:
          title: Git Repository URL
          type: string
          description: Git repository URL for source code
          placeholder: https://github.com/username/my-app.git
        
        gitBranch:
          title: Git Branch
          type: string
          description: Git branch to deploy
          default: main
        
        buildStrategy:
          title: Build Strategy
          type: string
          description: Source-to-Image build strategy
          enum:
            - nodejs
            - python
            - java
            - golang
            - php
            - ruby
            - dotnet
          enumNames:
            - Node.js
            - Python
            - Java (Maven/Gradle)
            - Go
            - PHP
            - Ruby
            - .NET Core
        
        buildEnvironment:
          title: Build Environment Variables
          type: object
          description: Environment variables for the build process
          additionalProperties:
            type: string
    
    - title: Resource Configuration
      required:
        - environment
        - region
      properties:
        environment:
          title: Environment
          type: string
          description: Target environment for deployment
          default: production
          enum:
            - development
            - staging
            - production
          enumNames:
            - Development (Small)
            - Staging (Medium) 
            - Production (Large)
        
        region:
          title: Region
          type: string
          description: Deployment region
          default: us-east-1
          enum:
            - us-east-1
            - us-west-2
            - eu-west-1
            - ap-southeast-1
        
        scaling:
          title: Scaling Configuration
          type: object
          properties:
            minReplicas:
              title: Minimum Replicas
              type: integer
              description: Minimum number of pods
              default: 1
              minimum: 1
              maximum: 10
            maxReplicas:
              title: Maximum Replicas
              type: integer
              description: Maximum number of pods for auto-scaling
              default: 5
              minimum: 1
              maximum: 50
            targetCPUPercent:
              title: Target CPU Percentage
              type: integer
              description: CPU percentage to trigger scaling
              default: 70
              minimum: 10
              maximum: 90
        
        resources:
          title: Resource Limits
          type: object
          properties:
            cpu:
              title: CPU Cores
              type: number
              description: Number of CPU cores per pod
              default: 0.5
              minimum: 0.1
              maximum: 8
              multipleOf: 0.1
            memory:
              title: Memory (GB)
              type: number
              description: Memory per pod in gigabytes
              default: 1
              minimum: 0.25
              maximum: 32
              multipleOf: 0.25
            storage:
              title: Persistent Storage (GB)
              type: number
              description: Persistent storage if needed
              default: 0
              minimum: 0
              maximum: 500
    
    - title: Networking & Features
      properties:
        networking:
          title: Networking Configuration
          type: object
          properties:
            ingress:
              title: Enable Ingress
              type: boolean
              description: Create ingress for external access
              default: true
            customDomain:
              title: Custom Domain
              type: string
              description: Custom domain name (optional)
              placeholder: my-app.example.com
        
        additionalFeatures:
          title: Additional Features
          type: array
          description: Select additional features
          items:
            type: string
            enum:
              - monitoring
              - logging
              - ssl-certificates
              - load-balancer
              - database
              - redis
          uniqueItems: true
          ui:widget: checkboxes
        
        database:
          title: Database Configuration
          when:
            properties:
              additionalFeatures:
                contains:
                  const: database
          type: object
          properties:
            type:
              title: Database Type
              type: string
              enum:
                - postgresql
                - mysql
                - mongodb
              default: postgresql
            size:
              title: Database Size
              type: string
              enum:
                - small
                - medium
                - large
              enumNames:
                - Small (1GB storage, 0.5 CPU)
                - Medium (10GB storage, 1 CPU)
                - Large (50GB storage, 2 CPU)
              default: small

  steps:
    - id: validate-subscription
      name: Validate Subscription
      action: tollgate:validate-subscription
      input:
        userId: ${{ user.entity.metadata.name }}
        requiredTier: basic
        requiredFeatures:
          - kubernetes-deployment
    
    - id: calculate-price
      name: Calculate Deployment Cost
      action: tollgate:calculate-price
      input:
        resources:
          - type: web-app
            cpu: ${{ parameters.resources.cpu or (parameters.environment == 'development' and 0.25 or (parameters.environment == 'staging' and 0.5 or 1)) }}
            memory: ${{ parameters.resources.memory or (parameters.environment == 'development' and 0.5 or (parameters.environment == 'staging' and 1 or 2)) }}
            storage: ${{ parameters.resources.storage or 0 }}
            replicas: ${{ parameters.scaling.minReplicas or 1 }}
        region: ${{ parameters.region }}
        duration: 720
        additionalFeatures: ${{ parameters.additionalFeatures }}
    
    - id: database-pricing
      name: Add Database Pricing
      when: ${{ 'database' in parameters.additionalFeatures }}
      action: tollgate:calculate-price
      input:
        resources:
          - type: ${{ parameters.database.type }}
            cpu: ${{ parameters.database.size == 'small' and 0.5 or (parameters.database.size == 'medium' and 1 or 2) }}
            memory: ${{ parameters.database.size == 'small' and 1 or (parameters.database.size == 'medium' and 2 or 4) }}
            storage: ${{ parameters.database.size == 'small' and 1 or (parameters.database.size == 'medium' and 10 or 50) }}
        region: ${{ parameters.region }}
        duration: 720
    
    - id: cost-approval-gate
      name: Cost Approval Gate
      when: ${{ (steps['calculate-price'].output.totalCost + (steps['database-pricing'].output.totalCost or 0)) > 50 }}
      action: tollgate:create-payment-intent
      input:
        amount: ${{ steps['calculate-price'].output.totalCost + (steps['database-pricing'].output.totalCost or 0) }}
        userId: ${{ user.entity.metadata.name }}
        description: "Web app deployment: ${{ parameters.name }}"
        metadata:
          template: web-app-deployment
          deploymentType: ${{ parameters.deploymentType }}
          environment: ${{ parameters.environment }}
    
    - id: payment-confirmation
      name: Wait for Payment Confirmation
      when: ${{ steps['cost-approval-gate'].output.paymentIntentId }}
      action: tollgate:confirm-payment
      input:
        paymentIntentId: ${{ steps['cost-approval-gate'].output.paymentIntentId }}
        timeoutMinutes: 10
    
    - id: create-app-cr
      name: Create Application Custom Resource
      action: kubernetes:create-cr
      input:
        apiVersion: apps.example.com/v1
        kind: WebApp
        name: ${{ parameters.name }}
        namespace: ${{ parameters.environment }}
        spec:
          deployment:
            type: ${{ parameters.deploymentType }}
            container:
              image: ${{ parameters.containerImage }}
              port: ${{ parameters.containerPort or 8080 }}
            source:
              git:
                repository: ${{ parameters.gitRepository }}
                branch: ${{ parameters.gitBranch or 'main' }}
              buildStrategy: ${{ parameters.buildStrategy }}
              buildEnv: ${{ parameters.buildEnvironment or {} }}
          
          resources:
            requests:
              cpu: ${{ steps['calculate-price'].output.breakdown[0].quantity }}
              memory: ${{ steps['calculate-price'].output.breakdown[1].quantity }}Gi
            limits:
              cpu: ${{ steps['calculate-price'].output.breakdown[0].quantity * 2 }}
              memory: ${{ steps['calculate-price'].output.breakdown[1].quantity * 2 }}Gi
          
          scaling:
            minReplicas: ${{ parameters.scaling.minReplicas or 1 }}
            maxReplicas: ${{ parameters.scaling.maxReplicas or 5 }}
            targetCPU: ${{ parameters.scaling.targetCPUPercent or 70 }}
          
          storage:
            enabled: ${{ parameters.resources.storage > 0 }}
            size: ${{ parameters.resources.storage }}Gi
            storageClass: gp3
          
          networking:
            ingress:
              enabled: ${{ parameters.networking.ingress }}
              host: ${{ parameters.networking.customDomain or parameters.name + '.' + parameters.environment + '.example.com' }}
              tls: ${{ 'ssl-certificates' in parameters.additionalFeatures }}
          
          monitoring:
            enabled: ${{ 'monitoring' in parameters.additionalFeatures }}
          
          logging:
            enabled: ${{ 'logging' in parameters.additionalFeatures }}
          
          database:
            enabled: ${{ 'database' in parameters.additionalFeatures }}
            type: ${{ parameters.database.type }}
            size: ${{ parameters.database.size }}
          
          redis:
            enabled: ${{ 'redis' in parameters.additionalFeatures }}
        
        metadata:
          labels:
            app.kubernetes.io/name: ${{ parameters.name }}
            app.kubernetes.io/component: web-app
            app.kubernetes.io/managed-by: backstage-scaffolder
            backstage.io/template: web-app-deployment
          annotations:
            backstage.io/deployment-cost: ${{ steps['calculate-price'].output.totalCost + (steps['database-pricing'].output.totalCost or 0) }}
            backstage.io/monthly-cost: ${{ steps['calculate-price'].output.monthlyCost + (steps['database-pricing'].output.monthlyCost or 0) }}
            backstage.io/payment-reference: ${{ steps['payment-confirmation'].output.transactionId or 'auto-approved' }}
    
    - id: create-database-cr
      name: Create Database Custom Resource
      when: ${{ 'database' in parameters.additionalFeatures }}
      action: kubernetes:create-cr
      input:
        apiVersion: data.example.com/v1
        kind: Database
        name: ${{ parameters.name }}-db
        namespace: ${{ parameters.environment }}
        spec:
          type: ${{ parameters.database.type }}
          size: ${{ parameters.database.size }}
          backup:
            enabled: true
            schedule: "0 2 * * *"
            retention: "7d"
          connections:
            maxConnections: ${{ parameters.database.size == 'small' and 20 or (parameters.database.size == 'medium' and 100 or 500) }}
          resources:
            requests:
              cpu: ${{ steps['database-pricing'].output.breakdown[0].quantity }}
              memory: ${{ steps['database-pricing'].output.breakdown[1].quantity }}Gi
            limits:
              cpu: ${{ steps['database-pricing'].output.breakdown[0].quantity * 2 }}
              memory: ${{ steps['database-pricing'].output.breakdown[1].quantity * 2 }}Gi
        metadata:
          labels:
            app.kubernetes.io/name: ${{ parameters.name }}-db
            app.kubernetes.io/component: database
            app.kubernetes.io/part-of: ${{ parameters.name }}

  output:
    links:
      - title: Application URL
        url: https://${{ parameters.networking.customDomain or parameters.name + '.' + parameters.environment + '.example.com' }}
        when: ${{ parameters.networking.ingress }}
      - title: Cost Breakdown
        url: data:application/json,${{ steps['calculate-price'].output.breakdown | dump }}
      - title: Payment Receipt
        url: ${{ steps['payment-confirmation'].output.receiptUrl }}
        when: ${{ steps['payment-confirmation'].output.receiptUrl }}