openapi: 3.0.3
info:
  title: TenantPilot Backup Scheduling (Spec 032)
  version: "0.1"
  description: |
    Conceptual contract for Backup Scheduling MVP. TenantPilot uses Filament/Livewire;
    these endpoints describe behavior for review/testing and future API alignment.
servers:
  - url: https://{host}
    variables:
      host:
        default: example.local

paths:
  /tenants/{tenantId}/backup-schedules:
    get:
      summary: List backup schedules for a tenant
      parameters:
        - $ref: '#/components/parameters/TenantId'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BackupSchedule'
    post:
      summary: Create a backup schedule
      parameters:
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BackupScheduleCreate'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BackupSchedule'
        '422':
          description: Validation error (e.g. unknown policy_types)

  /tenants/{tenantId}/backup-schedules/{scheduleId}:
    patch:
      summary: Update a backup schedule
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/ScheduleId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BackupScheduleUpdate'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BackupSchedule'
        '422':
          description: Validation error
    delete:
      summary: Delete (or disable) a schedule
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/ScheduleId'
      responses:
        '204':
          description: Deleted

  /tenants/{tenantId}/backup-schedules/{scheduleId}/run-now:
    post:
      summary: Trigger a run immediately
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/ScheduleId'
      responses:
        '202':
          description: Accepted (run created and job dispatched)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BackupScheduleRun'

  /tenants/{tenantId}/backup-schedules/{scheduleId}/retry:
    post:
      summary: Create a new run as retry
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/ScheduleId'
      responses:
        '202':
          description: Accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BackupScheduleRun'

  /tenants/{tenantId}/backup-schedules/{scheduleId}/runs:
    get:
      summary: List runs for a schedule
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/ScheduleId'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BackupScheduleRun'

components:
  parameters:
    TenantId:
      name: tenantId
      in: path
      required: true
      schema:
        type: integer
    ScheduleId:
      name: scheduleId
      in: path
      required: true
      schema:
        type: integer

  schemas:
    BackupSchedule:
      type: object
      required: [id, tenant_id, name, is_enabled, timezone, frequency, time_of_day, policy_types, retention_keep_last]
      properties:
        id: { type: integer }
        tenant_id: { type: integer }
        name: { type: string }
        is_enabled: { type: boolean }
        timezone: { type: string, example: "Europe/Berlin" }
        frequency: { type: string, enum: [daily, weekly] }
        time_of_day: { type: string, example: "02:00:00" }
        days_of_week:
          type: array
          nullable: true
          items: { type: integer, minimum: 1, maximum: 7 }
        policy_types:
          type: array
          items: { type: string }
          description: Must be keys from config('tenantpilot.supported_policy_types').
        include_foundations: { type: boolean }
        retention_keep_last: { type: integer, minimum: 1 }
        last_run_at: { type: string, format: date-time, nullable: true }
        last_run_status: { type: string, nullable: true }
        next_run_at: { type: string, format: date-time, nullable: true }

    BackupScheduleCreate:
      allOf:
        - $ref: '#/components/schemas/BackupScheduleUpdate'
        - type: object
          required: [name, timezone, frequency, time_of_day, policy_types]

    BackupScheduleUpdate:
      type: object
      properties:
        name: { type: string }
        is_enabled: { type: boolean }
        timezone: { type: string }
        frequency: { type: string, enum: [daily, weekly] }
        time_of_day: { type: string }
        days_of_week:
          type: array
          nullable: true
          items: { type: integer, minimum: 1, maximum: 7 }
        policy_types:
          type: array
          items: { type: string }
        include_foundations: { type: boolean }
        retention_keep_last: { type: integer, minimum: 1 }

    BackupScheduleRun:
      type: object
      required: [id, backup_schedule_id, tenant_id, scheduled_for, status]
      properties:
        id: { type: integer }
        backup_schedule_id: { type: integer }
        tenant_id: { type: integer }
        scheduled_for: { type: string, format: date-time }
        started_at: { type: string, format: date-time, nullable: true }
        finished_at: { type: string, format: date-time, nullable: true }
        status: { type: string, enum: [running, success, partial, failed, canceled, skipped] }
        summary:
          type: object
          additionalProperties: true
        error_code: { type: string, nullable: true }
        error_message: { type: string, nullable: true }
        backup_set_id: { type: integer, nullable: true }
