openapi: 3.1.0
info:
  title: Route Cost API
  description: |
    Australian-aware trip fuel cost API. Given an origin, destination, and vehicle,
    returns distance, duration, fuel needed, cost (with excise + GST breakdown),
    and CO2e emissions in a single call.
  version: 0.1.0
  contact:
    name: Route Cost API
    url: https://routecost.com.au
    email: support@routecost.com.au
  license:
    name: Proprietary
servers:
  - url: https://api.routecost.com.au
    description: Production
  - url: http://localhost:3000
    description: Local dev

security:
  - BearerAuth: []

paths:
  /v1/route-cost:
    post:
      summary: Calculate fuel cost, distance, time, and emissions for a trip
      operationId: calculateRouteCost
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RouteCostRequest"
            examples:
              brisbaneToSydney:
                summary: Brisbane to Sydney, 2-passenger ULP vehicle
                value:
                  origin: "Brisbane, QLD"
                  destination: "Sydney, NSW"
                  vehicle:
                    consumption: 8.5
                    fuelType: ULP
                    tankSize: 60
                  passengers: 2
                  roundTrip: false
                  fuelPriceSource: live
      responses:
        "200":
          description: Successful calculation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RouteCostResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "502":
          $ref: "#/components/responses/UpstreamError"

  /v1/health:
    get:
      summary: Service health check
      operationId: healthCheck
      security: []
      responses:
        "200":
          description: Healthy
        "503":
          description: Degraded

  /v1/fuel-prices/{state}:
    get:
      summary: Current fuel prices by state
      operationId: fuelPricesByState
      parameters:
        - name: state
          in: path
          required: true
          schema:
            type: string
            enum: [NSW, VIC, QLD, WA, SA, TAS, NT, ACT]
      responses:
        "200":
          description: Current prices

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key

  schemas:
    Coordinates:
      type: object
      required: [lat, lng]
      properties:
        lat: { type: number, format: double, example: -27.4698 }
        lng: { type: number, format: double, example: 153.0251 }

    Location:
      oneOf:
        - type: string
          description: Free-text address (will be geocoded)
          example: "Brisbane, QLD"
        - $ref: "#/components/schemas/Coordinates"

    Vehicle:
      type: object
      required: [consumption]
      properties:
        consumption:
          type: number
          description: Combined-cycle fuel consumption in L/100km
          minimum: 0.1
          maximum: 50
          example: 8.5
        fuelType:
          type: string
          enum: [ULP, E10, P95, P98, Diesel, LPG]
          default: ULP
        tankSize:
          type: number
          description: Tank capacity in litres (optional, used for fuel-stops calc)
          minimum: 1
          maximum: 500

    RouteCostRequest:
      type: object
      required: [origin, destination, vehicle]
      properties:
        origin: { $ref: "#/components/schemas/Location" }
        destination: { $ref: "#/components/schemas/Location" }
        vehicle: { $ref: "#/components/schemas/Vehicle" }
        passengers:
          type: integer
          minimum: 1
          maximum: 99
          default: 1
        roundTrip:
          type: boolean
          default: false
        fuelPriceSource:
          type: string
          enum: [live, manual, average]
          default: live
        fuelPricePerLitre:
          type: number
          description: Required when fuelPriceSource is "manual"
          minimum: 0

    RouteCostResponse:
      type: object
      properties:
        route:
          type: object
          properties:
            distanceKm: { type: number }
            durationMinutes: { type: integer }
            polyline: { type: string }
            origin: { type: object }
            destination: { type: object }
            routingBackend: { type: string, enum: [ors, osrm] }
        fuel:
          type: object
          properties:
            litres: { type: number }
            pricePerLitre: { type: number }
            pricePerLitreSource: { type: string }
            fuelStopsNeeded: { type: integer }
            fuelType: { type: string }
        cost:
          type: object
          properties:
            totalAud: { type: number }
            perPersonAud: { type: number }
            excisePortionAud: { type: number }
            gstPortionAud: { type: number }
            fuelBaseAud: { type: number }
        emissions:
          type: object
          properties:
            co2eKg: { type: number }
            factorKgPerL: { type: number }
            methodology: { type: string }
        meta:
          type: object
          properties:
            requestId: { type: string }
            computedAt: { type: string, format: date-time }
            version: { type: string }

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string }
            message: { type: string }
            details: { type: object }
            requestId: { type: string }

  responses:
    BadRequest:
      description: Invalid input
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    NotFound:
      description: Route or address not found
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    RateLimited:
      description: Rate limit exceeded for your tier
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    UpstreamError:
      description: Upstream service (routing, geocoding, fuel prices) failed
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
