{
 "openapi": "3.0.3",
 "info": {
  "title": "API Tempo Açores",
  "version": "1.0.0",
  "description": "API da UC de PDM (CTeSP DAW, ESTA, Universidade dos Açores, 2026/27).\n\n1. Troca o teu `clientId` e `clientSecret` por um token em **POST /v1/auth/token**.\n2. Envia o token em todos os outros pedidos: `Authorization: Bearer <token>`. Aqui no Swagger, usa o botão **Authorize**.\n3. O token dura 1 hora. Quando expirar (401), pede outro.\n\nA previsão vem do IPMA (dados abertos) e é atualizada de 30 em 30 minutos. Os relatos são partilhados pela turma: todos veem os de todos, cada um só altera os seus.\n\nErros vêm sempre assim: `{\"error\": {\"code\": \"not_found\", \"message\": \"...\"}}`."
 },
 "servers": [
  {
   "url": "/"
  }
 ],
 "tags": [
  {
   "name": "Autenticação"
  },
  {
   "name": "Ilhas e trilhos"
  },
  {
   "name": "Previsão"
  },
  {
   "name": "Relatos"
  }
 ],
 "paths": {
  "/v1/auth/token": {
   "post": {
    "tags": [
     "Autenticação"
    ],
    "summary": "Obter um token",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TokenRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Token válido durante 1 hora.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Token"
        }
       }
      }
     },
     "400": {
      "description": "Pedido inválido (campo em falta, texto vazio ou com mais de 500 caracteres, fotografia que não é JPEG/PNG/WebP).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "bad_request",
          "message": "Envia JSON com clientId e clientSecret, e o header Content-Type: application/json."
         }
        }
       }
      }
     },
     "401": {
      "description": "clientId ou clientSecret errados.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "clientId ou clientSecret errados."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/me": {
   "get": {
    "tags": [
     "Autenticação"
    ],
    "summary": "Quem sou eu (para testar o token)",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "responses": {
     "200": {
      "description": "O aluno do token.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Me"
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/islands": {
   "get": {
    "tags": [
     "Ilhas e trilhos"
    ],
    "summary": "As nove ilhas",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "responses": {
     "200": {
      "description": "Lista de ilhas.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/Island"
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/islands/{id}": {
   "get": {
    "tags": [
     "Ilhas e trilhos"
    ],
    "summary": "Uma ilha",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id da ilha",
      "schema": {
       "type": "string",
       "example": "pico"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "A ilha.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Island"
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhuma ilha com o id \"atlantida\"."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/islands/{id}/forecast": {
   "get": {
    "tags": [
     "Previsão"
    ],
    "summary": "Previsão a 5 dias de uma ilha (IPMA)",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id da ilha",
      "schema": {
       "type": "string",
       "example": "sao-miguel"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "A previsão.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Forecast"
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhuma ilha com o id \"atlantida\"."
         }
        }
       }
      }
     },
     "502": {
      "description": "O IPMA não respondeu e não há previsão em cache.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "upstream_error",
          "message": "O IPMA não respondeu. Tenta daqui a pouco."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/trails": {
   "get": {
    "tags": [
     "Ilhas e trilhos"
    ],
    "summary": "Trilhos, de todas as ilhas ou de uma",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "islandId",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "example": "faial"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Lista de trilhos.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/Trail"
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhuma ilha com o id \"atlantida\"."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/trails/{id}": {
   "get": {
    "tags": [
     "Ilhas e trilhos"
    ],
    "summary": "Um trilho",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id do trilho",
      "schema": {
       "type": "string",
       "example": "lagoa-do-fogo"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "O trilho.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Trail"
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhum trilho com o id \"atlantida\"."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/reports": {
   "get": {
    "tags": [
     "Relatos"
    ],
    "summary": "Feed de relatos da turma (mais recentes primeiro)",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "islandId",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "example": "pico"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "default": 50,
       "minimum": 1,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Lista de relatos.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/Report"
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhuma ilha com o id \"atlantida\"."
         }
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "Relatos"
    ],
    "summary": "Criar um relato (só texto em JSON, ou texto e fotografia em multipart)",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/NewReport"
       }
      },
      "multipart/form-data": {
       "schema": {
        "type": "object",
        "required": [
         "islandId",
         "text"
        ],
        "properties": {
         "islandId": {
          "type": "string",
          "example": "pico"
         },
         "text": {
          "type": "string",
          "example": "Nevoeiro a meio da montanha."
         },
         "photo": {
          "type": "string",
          "format": "binary",
          "description": "JPEG, PNG ou WebP, até 8 MB. É reduzida a 1280 px."
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "O relato criado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Report"
        }
       }
      }
     },
     "400": {
      "description": "Pedido inválido (campo em falta, texto vazio ou com mais de 500 caracteres, fotografia que não é JPEG/PNG/WebP).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "bad_request",
          "message": "O texto do relato não pode estar vazio."
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Não há nenhuma ilha com o id \"atlantida\"."
         }
        }
       }
      }
     },
     "413": {
      "description": "Fotografia com mais de 8 MB.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/reports/{id}": {
   "get": {
    "tags": [
     "Relatos"
    ],
    "summary": "Um relato",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id do relato",
      "schema": {
       "type": "string",
       "example": ""
      }
     }
    ],
    "responses": {
     "200": {
      "description": "O relato.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Report"
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Esse relato não existe."
         }
        }
       }
      }
     }
    }
   },
   "put": {
    "tags": [
     "Relatos"
    ],
    "summary": "Alterar o texto ou a ilha de um relato teu",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id do relato",
      "schema": {
       "type": "string",
       "example": ""
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EditReport"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "O relato alterado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Report"
        }
       }
      }
     },
     "400": {
      "description": "Pedido inválido (campo em falta, texto vazio ou com mais de 500 caracteres, fotografia que não é JPEG/PNG/WebP).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "bad_request",
          "message": "O texto do relato não pode estar vazio."
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "403": {
      "description": "O relato não é teu.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "forbidden",
          "message": "Só podes alterar os teus relatos."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Esse relato não existe."
         }
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Relatos"
    ],
    "summary": "Apagar um relato teu",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id do relato",
      "schema": {
       "type": "string",
       "example": ""
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Apagado."
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "403": {
      "description": "O relato não é teu.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "forbidden",
          "message": "Só podes alterar os teus relatos."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Esse relato não existe."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/reports/{id}/photo": {
   "put": {
    "tags": [
     "Relatos"
    ],
    "summary": "Pôr ou substituir a fotografia de um relato teu",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id do relato",
      "schema": {
       "type": "string",
       "example": ""
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "type": "object",
        "required": [
         "photo"
        ],
        "properties": {
         "photo": {
          "type": "string",
          "format": "binary"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "O relato com a fotografia nova.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Report"
        }
       }
      }
     },
     "400": {
      "description": "Pedido inválido (campo em falta, texto vazio ou com mais de 500 caracteres, fotografia que não é JPEG/PNG/WebP).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "bad_request",
          "message": "O texto do relato não pode estar vazio."
         }
        }
       }
      }
     },
     "401": {
      "description": "Sem token, token inválido ou expirado.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "unauthorized",
          "message": "O token expirou. Pede um novo em POST /v1/auth/token."
         }
        }
       }
      }
     },
     "403": {
      "description": "O relato não é teu.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "forbidden",
          "message": "Só podes alterar os teus relatos."
         }
        }
       }
      }
     },
     "404": {
      "description": "Não existe.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "error": {
          "code": "not_found",
          "message": "Esse relato não existe."
         }
        }
       }
      }
     },
     "413": {
      "description": "Fotografia com mais de 8 MB.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearerAuth": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "JWT"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "object",
      "properties": {
       "code": {
        "type": "string",
        "example": "not_found",
        "description": "bad_request, unauthorized, forbidden, not_found, too_large, upstream_error ou internal_error"
       },
       "message": {
        "type": "string",
        "example": "Esse relato não existe."
       }
      },
      "required": [
       "code",
       "message"
      ]
     }
    },
    "required": [
     "error"
    ]
   },
   "TokenRequest": {
    "type": "object",
    "required": [
     "clientId",
     "clientSecret"
    ],
    "properties": {
     "clientId": {
      "type": "string",
      "example": "pdm-ab12cd"
     },
     "clientSecret": {
      "type": "string",
      "example": "o-teu-segredo"
     }
    }
   },
   "Token": {
    "type": "object",
    "properties": {
     "accessToken": {
      "type": "string"
     },
     "tokenType": {
      "type": "string",
      "example": "Bearer"
     },
     "expiresIn": {
      "type": "integer",
      "example": 3600
     }
    },
    "required": [
     "accessToken",
     "tokenType",
     "expiresIn"
    ]
   },
   "Me": {
    "type": "object",
    "properties": {
     "clientId": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "tokenExpiresAt": {
      "type": "integer",
      "description": "Unix timestamp"
     }
    },
    "required": [
     "clientId",
     "name",
     "tokenExpiresAt"
    ]
   },
   "Island": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "example": "sao-miguel"
     },
     "name": {
      "type": "string",
      "example": "São Miguel"
     },
     "imageUrl": {
      "type": "string",
      "example": "https://api-pdm.sublimecipher.com/static/islands/sao_miguel.jpg"
     },
     "trailCount": {
      "type": "integer",
      "example": 3
     }
    },
    "required": [
     "id",
     "name",
     "imageUrl",
     "trailCount"
    ]
   },
   "Trail": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "example": "montanha-do-pico"
     },
     "name": {
      "type": "string"
     },
     "islandId": {
      "type": "string"
     },
     "islandName": {
      "type": "string"
     },
     "imageUrl": {
      "type": "string"
     },
     "distanceKm": {
      "type": "number",
      "example": 7.6
     },
     "duration": {
      "type": "string",
      "example": "7 h"
     },
     "difficulty": {
      "type": "string",
      "enum": [
       "easy",
       "medium",
       "hard"
      ]
     },
     "difficultyLabel": {
      "type": "string",
      "example": "Difícil"
     },
     "description": {
      "type": "string"
     }
    },
    "required": [
     "id",
     "name",
     "islandId",
     "islandName",
     "imageUrl",
     "distanceKm",
     "duration",
     "difficulty",
     "difficultyLabel",
     "description"
    ]
   },
   "Forecast": {
    "type": "object",
    "properties": {
     "islandId": {
      "type": "string",
      "example": "sao-miguel"
     },
     "islandName": {
      "type": "string",
      "example": "São Miguel"
     },
     "location": {
      "type": "string",
      "example": "Ponta Delgada"
     },
     "source": {
      "type": "string",
      "example": "IPMA"
     },
     "updatedAt": {
      "type": "string",
      "example": "2026-10-14T13:31:02",
      "description": "Hora local dos Açores em que a API foi buscar a previsão ao IPMA."
     },
     "days": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Day"
      }
     }
    },
    "required": [
     "islandId",
     "islandName",
     "location",
     "source",
     "updatedAt",
     "days"
    ]
   },
   "Day": {
    "type": "object",
    "properties": {
     "date": {
      "type": "string",
      "format": "date",
      "example": "2026-10-13"
     },
     "weatherType": {
      "type": "object",
      "properties": {
       "id": {
        "type": "integer",
        "example": 3
       },
       "description": {
        "type": "string",
        "example": "Céu parcialmente nublado"
       },
       "category": {
        "type": "string",
        "enum": [
         "sunny",
         "partlyCloudy",
         "cloudy",
         "rain",
         "storm"
        ],
        "example": "partlyCloudy"
       }
      },
      "required": [
       "id",
       "description",
       "category"
      ]
     },
     "tMin": {
      "type": "number",
      "example": 17.6
     },
     "tMax": {
      "type": "number",
      "example": 23.6
     },
     "rainChance": {
      "type": "integer",
      "example": 20
     },
     "wind": {
      "type": "object",
      "properties": {
       "direction": {
        "type": "string",
        "example": "SE"
       },
       "class": {
        "type": "integer",
        "example": 2
       },
       "description": {
        "type": "string",
        "example": "Moderado"
       }
      },
      "required": [
       "direction",
       "class",
       "description"
      ]
     }
    },
    "required": [
     "date",
     "weatherType",
     "tMin",
     "tMax",
     "rainChance",
     "wind"
    ]
   },
   "NewReport": {
    "type": "object",
    "required": [
     "islandId",
     "text"
    ],
    "properties": {
     "islandId": {
      "type": "string",
      "example": "pico"
     },
     "text": {
      "type": "string",
      "maxLength": 500,
      "example": "Nevoeiro a meio da montanha."
     }
    }
   },
   "EditReport": {
    "type": "object",
    "properties": {
     "islandId": {
      "type": "string"
     },
     "text": {
      "type": "string",
      "maxLength": 500
     }
    }
   },
   "Report": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "islandId": {
      "type": "string"
     },
     "islandName": {
      "type": "string"
     },
     "text": {
      "type": "string"
     },
     "photoUrl": {
      "type": "string",
      "nullable": true
     },
     "author": {
      "type": "object",
      "properties": {
       "clientId": {
        "type": "string"
       },
       "name": {
        "type": "string"
       }
      },
      "required": [
       "clientId",
       "name"
      ]
     },
     "mine": {
      "type": "boolean",
      "description": "true se o relato é do aluno do token"
     },
     "createdAt": {
      "type": "string",
      "format": "date-time"
     },
     "updatedAt": {
      "type": "string",
      "format": "date-time"
     }
    },
    "required": [
     "id",
     "islandId",
     "islandName",
     "text",
     "photoUrl",
     "author",
     "mine",
     "createdAt",
     "updatedAt"
    ]
   }
  }
 }
}
