openapi: 3.1.0
info:
  title: VeezDelivery Core REST API
  description: >-
    Documentación y especificación oficial OpenAPI 3.1 para la API REST de VeezDelivery.
    Permite la cotización de envíos express, creación y seguimiento de pedidos, gestión de comercios e integraciones e-commerce (WooCommerce, Shopify, Odoo).
  version: 1.2.0
  contact:
    name: Soporte Técnico VeezDelivery
    email: soporte@veez.cl
    url: https://docs.veez.cl/

servers:
  - url: https://us-central1-veezdelivery.cloudfunctions.net/api/v1
    description: Servidor de Producción (Cloud Functions API Gateway)
  - url: http://127.0.0.1:5001/veezdelivery/us-central1/api/v1
    description: Emulador Local de Firebase

security:
  - ApiKeyAuth: []

paths:
  /health:
    get:
      summary: Estado de la API
      description: Retorna el estado actual del servicio API Gateway de VeezDelivery.
      security: []
      responses:
        '200':
          description: Servicio funcionando correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: healthy
                  version:
                    type: string
                    example: v1.2.0
                  service:
                    type: string
                    example: VeezDelivery Core API
                  timestamp:
                    type: string
                    format: date-time

  /shipping/quote:
    post:
      summary: Cotizar envío
      description: Calcula la tarifa de envío express, estimación de tiempo y vehículos disponibles según las direcciones y dimensiones.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
      responses:
        '200':
          description: Cotización generada exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /orders:
    post:
      summary: Crear pedido de delivery
      description: Registra una nueva orden de envío en VeezDelivery y asigna o encola un repartidor (courier).
      parameters:
        - in: header
          name: idempotency-key
          required: false
          schema:
            type: string
          description: Llave opcional para prevenir duplicación de órdenes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '201':
          description: Pedido creado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '200':
          description: Pedido duplicado retornado mediante idempotency-key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /orders/consolidate:
    post:
      summary: Consolidar lotes de pedidos (Batching)
      description: Agrupa múltiples pedidos de una misma zona geohash para asignación optimizada a un vehículo de mayor capacidad.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                geohash_zone:
                  type: string
                  example: "366r"
                target_car_type:
                  type: string
                  default: car
                  example: "car"
      responses:
        '200':
          description: Tarea de consolidación ejecutada
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  batches_created:
                    type: integer
                    example: 2

  /orders/{id}:
    get:
      summary: Obtener detalle y estado del pedido
      description: Devuelve la información actualizada de un pedido por ID de booking, ID externo o número de referencia.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
          description: ID del pedido en VeezDelivery o código de referencia.
      responses:
        '200':
          description: Detalle del pedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderDetails'
        '404':
          $ref: '#/components/responses/NotFound'

  /orders/{id}/cancel:
    post:
      summary: Cancelar pedido
      description: Cancela un pedido si aún se encuentra en estado pendiente o asignado antes de retiro.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  example: "Cliente solicitó cancelación"
      responses:
        '200':
          description: Pedido cancelado correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  booking_id:
                    type: string
                  status:
                    type: string
                    example: CANCELLED

  /orders/{id}/deliver:
    post:
      summary: Confirmar entrega con prueba (POD)
      description: Completa la entrega validando geofoto/geofencing y guardando evidencia fotográfica y firma digital.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                driver_id:
                  type: string
                coords:
                  $ref: '#/components/schemas/LatLng'
                photo_url:
                  type: string
                signature_url:
                  type: string
                geofence_radius:
                  type: number
                  default: 20
                bypass:
                  type: boolean
                  default: false
      responses:
        '200':
          description: Entrega confirmada con éxito
        '400':
          description: Error en geofencing o datos incompletos

  /tracking/{reference}:
    get:
      summary: Seguimiento público de envío
      description: Endpoint público sin autenticación requerida para tracking en tiempo real de repartidores y paquetes.
      security: []
      parameters:
        - in: path
          name: reference
          required: true
          schema:
            type: string
          description: Código de seguimiento o número de pedido.
      responses:
        '200':
          description: Información de seguimiento
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrackingResponse'

  /merchants/me:
    get:
      summary: Obtener perfil de comercio
      description: Retorna la información y configuración del comercio autenticado con la API key.
      responses:
        '200':
          description: Perfil del comercio

  /merchants/settings:
    post:
      summary: Actualizar ajustes de comercio
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Ajustes actualizados
    patch:
      summary: Actualizar parcialmente ajustes de comercio
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Ajustes actualizados

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: "Ingresa tu API Key de VeezDelivery en el header X-API-Key o vía Bearer token."

  responses:
    BadRequest:
      description: Solicitud inválida o faltan campos obligatorios.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: API Key ausente o inválida.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Recurso no encontrado.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  schemas:
    LatLng:
      type: object
      required: [lat, lng]
      properties:
        lat:
          type: number
          example: -33.4489
        lng:
          type: number
          example: -70.6693

    Address:
      type: object
      required: [address]
      properties:
        address:
          type: string
          example: "Av. Providencia 1234, Santiago"
        coords:
          $ref: '#/components/schemas/LatLng'
        number:
          type: string
        instructions:
          type: string

    QuoteRequest:
      type: object
      required: [origin, destination]
      properties:
        origin:
          $ref: '#/components/schemas/Address'
        destination:
          $ref: '#/components/schemas/Address'
        package_type:
          type: string
          example: "small_box"
        total_weight_kg:
          type: number
          example: 1.5
        prep_time_mins:
          type: integer
          example: 15

    QuoteResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        is_test:
          type: boolean
          example: false
        price:
          type: number
          example: 3500
        currency:
          type: string
          example: "CLP"
        estimated_time_mins:
          type: integer
          example: 30
        vehicle_type:
          type: string
          example: "motorcycle"

    CreateOrderRequest:
      type: object
      required: [pickup, dropoff, customer_name, customer_phone]
      properties:
        pickup:
          $ref: '#/components/schemas/Address'
        dropoff:
          $ref: '#/components/schemas/Address'
        customer_name:
          type: string
          example: "Juan Pérez"
        customer_phone:
          type: string
          example: "+56912345678"
        reference_id:
          type: string
          example: "ORD-9876"
        items:
          type: array
          items:
            type: object

    OrderResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        booking_id:
          type: string
          example: "-N123456789"
        tracking_url:
          type: string
          example: "https://veez.cl/tracking/ORD-9876"
        status:
          type: string
          example: "NEW"

    OrderDetails:
      type: object
      properties:
        success:
          type: boolean
          example: true
        order_id:
          type: string
        status:
          type: string
        pickup:
          $ref: '#/components/schemas/Address'
        dropoff:
          $ref: '#/components/schemas/Address'

    TrackingResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        reference:
          type: string
        status:
          type: string
          example: "IN_TRANSIT"
        driver:
          type: object
          properties:
            name:
              type: string
            phone:
              type: string
            location:
              $ref: '#/components/schemas/LatLng'

    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            code:
              type: string
              example: "INVALID_API_KEY"
            message:
              type: string
              example: "La API Key provista no existe o está inactiva"
