openapi: "3.0.3"
info:
  title: "PoupaTchê API"
  description: "API REST para monitoramento automático de preços via robôs configuráveis. Integre dados de preços reais ao seu sistema."
  version: "1.0.0"
  contact:
    url: "https://www.poupatche.com.br/api"

servers:
  - url: "https://www.poupatche.com.br/api/v1"
    description: "Servidor PoupaTchê"

security:
  - BearerToken: []
  - ApiTokenQuery: []

tags:
  - name: "Conta"
    description: "Dados do usuário autenticado"
  - name: "Robôs"
    description: "Gerenciamento de robôs de monitoramento"
  - name: "Relatórios"
    description: "Histórico e logs de eventos"
  - name: "Webhook"
    description: "Configuração de notificação automática via webhook"

components:
  securitySchemes:
    BearerToken:
      type: http
      scheme: bearer
      description: "Header: Authorization: Bearer SEU_TOKEN"
    ApiTokenQuery:
      type: apiKey
      in: query
      name: api_token
      description: "Query string: ?api_token=SEU_TOKEN"

  schemas:
    ApiResponse:
      type: object
      properties:
        success:
          type: boolean
        data:
          nullable: true
        message:
          type: string
        errors:
          type: object

    City:
      type: object
      properties:
        name:
          type: string
          example: "Porto Alegre"
        lat:
          type: number
          format: float
          example: -30.0277
          nullable: true
        lng:
          type: number
          format: float
          example: -51.2287
          nullable: true

    Robot:
      type: object
      properties:
        id:
          type: integer
          example: 42
        description:
          type: string
          example: "Arroz 5kg"
        max_price:
          type: number
          format: float
          example: 29.90
        hours:
          type: array
          items:
            type: integer
          example: [8, 18]
        cities:
          type: array
          items:
            $ref: "#/components/schemas/City"
        searches_per_day:
          type: integer
          example: 2
        state:
          type: boolean
          example: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    RobotInput:
      type: object
      required: [description, max_price, hours, cities]
      properties:
        description:
          type: string
          maxLength: 255
          example: "Arroz 5kg"
          description: "Nome do produto. Use cod:GTIN para busca por código de barras."
        max_price:
          type: number
          format: float
          minimum: 0
          example: 29.90
          description: "Preço máximo para disparo do alerta."
        hours:
          type: array
          items:
            type: integer
            minimum: 0
            maximum: 23
          minItems: 1
          example: [8, 18]
          description: "Horários de busca (0-23)."
        cities:
          type: array
          items:
            $ref: "#/components/schemas/City"
          minItems: 1
          example:
            - name: "Porto Alegre"
            - name: "Casa"
              lat: -30.0277
              lng: -51.2287
          description: "Cidades onde buscar. Informe lat/lng para busca por GPS."
        state:
          type: boolean
          default: true
          description: "true = ativo, false = inativo."

    RobotUpdate:
      type: object
      properties:
        description:
          type: string
          maxLength: 255
        max_price:
          type: number
          format: float
          minimum: 0
        hours:
          type: array
          items:
            type: integer
            minimum: 0
            maximum: 23
          minItems: 1
        cities:
          type: array
          items:
            $ref: "#/components/schemas/City"
          minItems: 1
        state:
          type: boolean

    EventLog:
      type: object
      properties:
        id:
          type: integer
        type:
          type: string
          enum: [user_action, system, api]
        action:
          type: string
          example: "robot_created"
        description:
          type: string
        data:
          type: object
          nullable: true
        ip_address:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time

    Webhook:
      type: object
      properties:
        webhook_url:
          type: string
          format: uri
          nullable: true
          example: "https://meusite.com/webhook/poupatche"

    WebhookInput:
      type: object
      required: [webhook_url]
      properties:
        webhook_url:
          type: string
          format: uri
          maxLength: 500
          example: "https://meusite.com/webhook/poupatche"
          description: "URL válida com esquema http ou https."

paths:
  /me:
    get:
      summary: "Dados do usuário autenticado"
      operationId: getMe
      tags: [Conta]
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          plan:
                            type: string
                          plan_label:
                            type: string
                          daily_limit:
                            type: integer
        "401":
          description: "Token inválido ou ausente"

  /robos:
    get:
      summary: "Lista todos os robôs"
      operationId: listRobots
      tags: [Robôs]
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Robot"
        "401":
          description: "Token inválido ou ausente"

    post:
      summary: "Cria um novo robô"
      operationId: createRobot
      tags: [Robôs]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RobotInput"
      responses:
        "201":
          description: "Robô criado"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Robot"
        "401":
          description: "Token inválido ou ausente"
        "422":
          description: "Dados inválidos"

  /robos/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
        description: "ID do robô"

    get:
      summary: "Detalhes de um robô"
      operationId: getRobot
      tags: [Robôs]
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Robot"
        "401":
          description: "Token inválido ou ausente"
        "404":
          description: "Robô não encontrado"

    put:
      summary: "Atualiza um robô"
      operationId: updateRobot
      tags: [Robôs]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RobotUpdate"
      responses:
        "200":
          description: "Robô atualizado"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Robot"
        "401":
          description: "Token inválido ou ausente"
        "404":
          description: "Robô não encontrado"
        "422":
          description: "Dados inválidos"

    delete:
      summary: "Exclui um robô"
      operationId: deleteRobot
      tags: [Robôs]
      responses:
        "200":
          description: "Robô excluído"
        "401":
          description: "Token inválido ou ausente"
        "404":
          description: "Robô não encontrado"

  /robos/{id}/reports:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer

    get:
      summary: "Últimos 50 eventos do robô"
      operationId: getRobotReports
      tags: [Robôs]
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/EventLog"
        "401":
          description: "Token inválido ou ausente"
        "404":
          description: "Robô não encontrado"

  /reports:
    get:
      summary: "Relatório de eventos (paginado)"
      operationId: getReports
      tags: [Relatórios]
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: per_page
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: sort
          in: query
          schema:
            type: string
            enum: [created_at, type, action, description]
            default: created_at
        - name: direction
          in: query
          schema:
            type: string
            enum: [asc, desc]
            default: desc
        - name: search
          in: query
          description: "Texto livre em description"
          schema:
            type: string
        - name: type
          in: query
          schema:
            type: string
            enum: [user_action, system, api]
        - name: action
          in: query
          description: "Ex: robot_created, search_run, api_request"
          schema:
            type: string
        - name: date_from
          in: query
          schema:
            type: string
            format: date
            example: "2026-06-01"
        - name: date_to
          in: query
          schema:
            type: string
            format: date
            example: "2026-06-30"
        - name: robot_id
          in: query
          schema:
            type: integer
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          items:
                            type: array
                            items:
                              $ref: "#/components/schemas/EventLog"
                          pagination:
                            type: object
                            properties:
                              total:
                                type: integer
                              per_page:
                                type: integer
                              current_page:
                                type: integer
                              last_page:
                                type: integer
                              from:
                                type: integer
                                nullable: true
                              to:
                                type: integer
                                nullable: true
                          sort:
                            type: string
                          direction:
                            type: string
        "401":
          description: "Token inválido ou ausente"

  /webhook:
    get:
      summary: "Consulta URL de webhook configurada"
      operationId: getWebhook
      tags: [Webhook]
      responses:
        "200":
          description: "Sucesso"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Webhook"
        "401":
          description: "Token inválido ou ausente"

    post:
      summary: "Configura ou atualiza URL de webhook"
      operationId: setWebhook
      tags: [Webhook]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookInput"
      responses:
        "200":
          description: "Webhook configurado"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Webhook"
        "401":
          description: "Token inválido ou ausente"
        "422":
          description: "URL inválida"

    delete:
      summary: "Remove URL de webhook"
      operationId: deleteWebhook
      tags: [Webhook]
      responses:
        "200":
          description: "Webhook removido"
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiResponse"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Webhook"
        "401":
          description: "Token inválido ou ausente"
