openapi: 3.1.0
info:
  title: API de Integração com Serviços Google (Premium)
  version: "1.0"
  description: >
    Esta API permite a usuários autenticados e com plano Premium interagir com
    serviços do Google como Drive, Gmail, Agenda e Planilhas.
servers:
  - url: "https://app.rodrigowillen.com.br"

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "Token de Acesso Pessoal gerado no painel da aplicação (JWT)."
  schemas:
    Email:
      type: object
      properties:
        to:
          type: string
          description: O e-mail do destinatário.
        subject:
          type: string
          description: O assunto do e-mail.
        body:
          type: string
          description: O corpo de texto do e-mail.
        drive_file_ids:
          type: array
          description: "(Opcional) Uma lista de IDs de arquivos do Google Drive para anexar."
          items:
            type: string
      required:
        - to
        - subject
        - body
    CalendarEvent:
      type: object
      properties:
        summary: { type: string }
        start_time: { type: string, format: date-time }
        end_time: { type: string, format: date-time }
        description: { type: string }
      required: [summary, start_time, end_time]
    SheetValues:
      type: object
      properties:
        range:
          type: string
          description: "O intervalo no formato A1 (ex: 'Página1!A1:B5')."
        values:
          type: array
          description: "Uma lista de listas contendo os valores das células (ex: [['Nome'], ['João']])."
          items:
            type: array
            items:
              type: string
      required: [range, values]
    ClearRangeBody:
      type: object
      properties:
        range:
          type: string
          description: "O intervalo a ser limpo (ex: 'Página1!A:C')."
      required: [range]
    NewWorksheet:
      type: object
      properties:
        title:
          type: string
          description: "O título para a nova página/aba."
      required: [title]

security:
  - BearerAuth: []

paths:
  # --- ROTAS DO GOOGLE DRIVE ---
  /api/drive/search:
    get:
      summary: Pesquisar arquivos no Drive
      operationId: searchDriveFiles
      tags:
        - Drive
      parameters:
        - name: q
          in: query
          required: true
          description: Termo a ser pesquisado no nome do arquivo.
          schema:
            type: string
      responses:
        '200':
          description: Lista de arquivos encontrados.
        '401':
          description: Token inválido.
  /api/drive/folders/search:
    get:
      summary: Pesquisar pastas no Drive
      operationId: searchDriveFolders
      tags:
        - Drive
      parameters:
        - name: q
          in: query
          required: true
          description: Nome da pasta a ser pesquisada.
          schema:
            type: string
      responses:
        '200':
          description: Lista de pastas encontradas.
        '401':
          description: Token inválido.
  /api/drive/files:
    post:
      summary: Criar um novo arquivo (texto, .docx, ou .xlsx) no Drive
      description: >
        Cria arquivos .txt, .docx, ou .xlsx. Para planilhas, 'file_content' pode ser uma string CSV. Para Word, o conteúdo é o texto do documento. Rota preferencial para criar arquivos.
      operationId: createDriveFile
      tags:
        - Drive
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                file_name:
                  type: string
                  description: "O nome do arquivo, incluindo a extensão (ex: 'documento.txt', 'oficio.docx', 'inventario.xlsx')."
                file_content:
                  type: string
                  description: "O conteúdo de texto do arquivo. Para planilhas, pode ser uma string formatada como CSV."
                folder_name:
                  type: string
                  description: "(Opcional) Nome da pasta para salvar o arquivo. A pasta será criada se não existir."
              required:
                - file_name
                - file_content
      responses:
        '201':
          description: Arquivo criado com sucesso.
        '401':
          description: Token inválido.
  /api/drive/files/{file_id}:
    patch:
      summary: Renomear um arquivo ou pasta
      operationId: renameDriveFile
      tags: [Drive]
      parameters:
        - name: file_id
          in: path
          required: true
          description: O ID do arquivo ou pasta a ser renomeado.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                new_name:
                  type: string
                  description: O novo nome para o arquivo/pasta.
              required: [new_name]
      responses:
        '200':
          description: Arquivo renomeado com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.
    delete:
      summary: Mover um arquivo ou pasta para a lixeira
      operationId: trashDriveFile
      tags: [Drive]
      parameters:
        - name: file_id
          in: path
          required: true
          description: O ID do arquivo ou pasta a ser movido para a lixeira.
          schema:
            type: string
      responses:
        '204':
          description: Arquivo movido para a lixeira com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.
  /api/drive/files/{file_id}/download:
    get:
      summary: Fazer o download de um arquivo
      operationId: downloadDriveFile
      tags: [Drive]
      parameters:
        - name: file_id
          in: path
          required: true
          description: O ID do arquivo a ser baixado.
          schema:
            type: string
      responses:
        '200':
          description: Conteúdo do arquivo.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '404':
          description: Arquivo não encontrado.
        '401':
          description: Não autorizado.

  /api/drive/create-doc:
    post:
      summary: Criar um documento Google Docs (em branco)
      operationId: createGoogleDoc
      tags: [Google Docs]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  description: O título do documento a ser criado.
              required: [title]
      responses:
        '201':
          description: Documento criado com sucesso.
        '400':
          description: Título não fornecido.
        '401':
          description: Não autorizado.

  /api/drive/create-doc-formatado:
    post:
      summary: Criar um documento Google Docs com conteúdo e formatação
      operationId: createFormattedGoogleDoc
      tags: [Google Docs]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  description: O título do documento.
                content:
                  type: string
                  description: O conteúdo de texto a ser inserido no documento.
              required: [title, content]
      responses:
        '201':
          description: Documento formatado criado com sucesso.
        '400':
          description: Parâmetros obrigatórios ausentes.
        '401':
          description: Não autorizado.

  /api/drive/files/{file_id}/export-docx:
    get:
      summary: Exportar um documento Google Docs como Word (.docx)
      operationId: exportDocxFile
      tags: [Google Docs]
      parameters:
        - name: file_id
          in: path
          required: true
          description: O ID do documento Google Docs a ser exportado.
          schema:
            type: string
      responses:
        '200':
          description: Arquivo Word .docx binário.
          content:
            application/vnd.openxmlformats-officedocument.wordprocessingml.document:
              schema:
                type: string
                format: binary
        '404':
          description: Arquivo não encontrado.
        '401':
          description: Não autorizado.

  /health:
    get:
      summary: Verificação de integridade e status da API
      operationId: healthCheck
      tags: [Sistema]
      security: []
      responses:
        '200':
          description: API operacional e saudável.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: "healthy" }
                  service: { type: string, example: "api-drive" }
                  version: { type: string, example: "1.0" }
                  runtime: { type: string, example: "python3.11" }

  # --- ROTAS DO GMAIL ---
  /api/gmail/search:
    get:
      summary: Pesquisar e-mails com uma query
      operationId: searchGmailMessages
      tags: [Gmail]
      parameters:
        - name: q
          in: query
          required: true
          description: "Query de busca do Gmail (ex: 'subject:relatório from:chefe')."
          schema: { type: string }
        - name: limit
          in: query
          description: "Número máximo de resultados (padrão: 25)."
          schema: { type: integer }
      responses:
        '200':
          description: Lista de IDs de e-mails encontrados.
        '401':
          description: Token inválido.
  /api/gmail/messages/{message_id}:
    get:
      summary: Obter detalhes de um e-mail específico
      operationId: getGmailMessageDetails
      tags: [Gmail]
      parameters:
        - { name: message_id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Detalhes completos do e-mail.
        '401':
          description: Token inválido.
        '404':
          description: E-mail não encontrado.
  /api/gmail/send:
    post:
      summary: Enviar um e-mail com anexos do Drive
      operationId: sendGmailEmail
      tags: [Gmail] 
      requestBody:
        required: true
        content:
          application/json:
            schema:
              { $ref: '#/components/schemas/Email' } 
        description: Dados para envio de e-mail com anexos
      responses:
        '200':
          description: E-mail enviado com sucesso
        '400':
          description: Requisição malformada
        '401':
          description: Token inválido ou não autorizado
        '500':
          description: Erro interno no servidor

  # --- ENDPOINTS DE RASCUNHO DO GMAIL ---
  /api/gmail/drafts:
    post:
      summary: Criar um rascunho com anexos opcionais do Drive
      operationId: createGmailDraft
      tags: [Gmail Drafts]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/Email' }
      responses:
        '201': { description: Rascunho criado com sucesso. }
        '400': { description: Requisição inválida. }

  /api/gmail/drafts/{draft_id}:
    get:
      summary: Obter um rascunho específico
      operationId: getGmailDraft
      tags: [Gmail Drafts]
      parameters:
        - { name: draft_id, in: path, required: true, schema: { type: string } }
      responses:
        '200': { description: Detalhes do rascunho. }
        '404': { description: Rascunho não encontrado. }
    delete:
      summary: Deletar um rascunho
      operationId: deleteGmailDraft
      tags: [Gmail Drafts]
      parameters:
        - { name: draft_id, in: path, required: true, schema: { type: string } }
      responses:
        '204': { description: Rascunho deletado com sucesso. }
        '404': { description: Rascunho não encontrado. }

  /api/gmail/drafts/{draft_id}/send:
    post:
      summary: Enviar um rascunho existente
      operationId: sendGmailDraft
      tags: [Gmail Drafts]
      parameters:
        - { name: draft_id, in: path, required: true, schema: { type: string } }
      responses:
        '200': { description: Rascunho enviado como e-mail. }
        '400': { description: Requisição inválida. }
        '404': { description: Rascunho não encontrado. }
   
  # --- ROTAS DO GOOGLE SHEETS ---
  /api/sheets/:
    post:
      summary: Criar uma nova Planilha Google
      operationId: createSheet
      tags: [Sheets]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  description: O título da nova planilha.
              required: [title]
      responses:
        '201':
          description: Planilha criada com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.
  
  /api/sheets/{spreadsheet_id}/values/{range_str}:
    get:
      summary: Ler valores de uma planilha
      operationId: getSheetValues
      tags: [Sheets]
      parameters:
        - name: spreadsheet_id
          in: path
          required: true
          description: O ID da planilha.
          schema: { type: string }
        - name: range_str
          in: path
          required: true
          description: "O intervalo a ser lido no formato A1 (ex: 'Página1!A1:B5')."
          schema: { type: string }
      responses:
        '200':
          description: Valores encontrados.
        '401':
          description: Não autorizado.
        '404':
          description: Planilha ou intervalo não encontrado.

  /api/sheets/{spreadsheet_id}/values:append:
    post:
      summary: Anexar valores a uma planilha
      operationId: appendSheetValues
      tags: [Sheets]
      parameters:
        - name: spreadsheet_id
          in: path
          required: true
          description: O ID da planilha.
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SheetValues' }
      responses:
        '200':
          description: Valores anexados com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.

  /api/sheets/{spreadsheet_id}/values:clear:
    post:
      summary: Limpar valores de uma planilha
      operationId: clearSheetValues
      tags: [Sheets]
      parameters:
        - name: spreadsheet_id
          in: path
          required: true
          description: O ID da planilha.
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ClearRangeBody' }
      responses:
        '200':
          description: Valores limpos com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.

  /api/sheets/{spreadsheet_id}/worksheets:
    post:
      summary: Adicionar uma nova página (aba)
      operationId: addWorksheet
      tags: [Sheets]
      parameters:
        - name: spreadsheet_id
          in: path
          required: true
          description: O ID da planilha.
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/NewWorksheet' }
      responses:
        '200':
          description: Página adicionada com sucesso.
        '400':
          description: Requisição inválida.
        '401':
          description: Não autorizado.

  # --- ROTAS DO GOOGLE CALENDAR ---
  /api/calendar/events:
    get:
      summary: Listar próximos eventos da agenda
      operationId: listCalendarEvents
      tags: [Calendar]
      responses:
        '200': { description: Lista de eventos. }
        '401': { description: Token inválido. }
    post:
      summary: Criar um novo evento na agenda
      operationId: createCalendarEvent
      tags: [Calendar]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CalendarEvent' }
      responses:
        '201': { description: Evento criado com sucesso. }
        '401': { description: Token inválido. }
  
  /api/calendar/events/{event_id}:
    get:
      summary: Obter detalhes de um evento específico
      operationId: getCalendarEvent
      tags: [Calendar]
      parameters:
        - { name: event_id, in: path, required: true, schema: { type: string } }
      responses:
        '200': { description: Detalhes do evento. }
        '404': { description: Evento não encontrado. }
    patch:
      summary: Atualizar um evento existente
      operationId: updateCalendarEvent
      tags: [Calendar]
      parameters:
        - { name: event_id, in: path, required: true, schema: { type: string } }
      requestBody:
        description: 'Um objeto JSON com os campos a serem atualizados (ex: summary, description).'
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                summary: { type: string }
                description: { type: string }
      responses:
        '200': { description: Evento atualizado com sucesso. }
        '400': { description: Requisição inválida. }
        '404': { description: Evento não encontrado. }
    delete:
      summary: Deletar um evento
      operationId: deleteCalendarEvent
      tags: [Calendar]
      parameters:
        - { name: event_id, in: path, required: true, schema: { type: string } }
      responses:
        '204': { description: Evento deletado com sucesso. }
        '404': { description: Evento não encontrado. }
