{
  "openapi": "3.0.3",
  "info": {
    "title": "Portfolio API",
    "version": "1.0.0",
    "description": "Documentation de l'API Portfolio (Projets, Compétences, Uploads, TinyMCE key validation)."
  },
  "tags": [
    { "name": "Projets", "description": "Gestion des projets (CRUD)" },
    { "name": "Compétences", "description": "Gestion des compétences (CRUD)" },
    { "name": "Uploads", "description": "Téléversement d'images et logos" },
    { "name": "TinyMCE", "description": "Validation de la clé éditeur" }
  ],
  "servers": [ { "url": "" } ],
  "paths": {
    "/api/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Authentification admin (retourne JWT)",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type":"object","properties":{"password":{"type":"string"}},"required":["password"]}, "example": {"password":"••••••"}}}},
        "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"type":"object","properties":{"token":{"type":"string"},"expiresIn":{"type":"integer"}}}, "example": {"token":"eyJhbGciOi...","expiresIn":3600}}}}, "401": {"description":"Invalid credentials"}}
      }
    },
    "/api/auth/me": {
      "get": {
        "tags": ["Auth"],
        "summary": "Infos sur le token courant",
        "security": [{"adminJwt":[]}],
        "responses": {"200": {"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"payload":{"type":"object"}}},"example":{"ok":true,"payload":{"role":"admin","exp":1700000000}}}}},"401":{"description":"Unauthorized"}}
      }
    },
    "/api/projets": {
      "get": {
        "tags": ["Projets"],
        "summary": "Liste des projets",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {"type": "array", "items": {"$ref": "#/components/schemas/Projet"}},
                "examples": {
                  "exemple": {
                    "summary": "Liste basique",
                    "value": [
                      {"id":1,"titre":"Portfolio","description":"Site personnel","date":"2025-01-01","type":"web","url":"https://exemple.dev","imagePath":"/images-projets/sample1.png","contenu":"<p>HTML riche...</p>"},
                      {"id":2,"titre":"API","description":"Backend Cloudflare","date":"2025-02-10","type":"api","url":null,"imagePath":null,"contenu":null}
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Projets"],
        "summary": "Créer un projet",
  "security": [{"adminJwt": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/ProjetInput"},
              "example": {
                "titre": "Nouvelle App",
                "description": "Description courte",
                "date": "2025-09-03",
                "type": "web",
                "url": "https://monapp.dev",
                "imagePath": "/images-projets/1693741111-exemple.png",
                "contenu": "<h2>Détails</h2><p>Corps riche...</p>"
              }
            }
          }
        },
        "responses": {
          "201": {"description": "Créé"},
          "400": {"description": "Données invalides"}
        }
      }
    },
    "/api/projets/{id}": {
      "get": {
        "tags": ["Projets"],
        "summary": "Obtenir un projet",
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "responses": {
          "200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Projet"}, "example": {"id":1,"titre":"Portfolio","description":"Site personnel","date":"2025-01-01","type":"web","url":"https://exemple.dev","imagePath":null,"contenu":"<p>...contenu...</p>"}}}},
          "404": {"description": "Non trouvé"}
        }
      },
      "put": {
        "tags": ["Projets"],
        "summary": "Mettre à jour un projet",
  "security": [{"adminJwt": []}],
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjetInput"}, "example": {"titre":"Titre MAJ","description":"Nouvelle desc","date":"2025-09-03","type":"api"}}}},
        "responses": {"200": {"description": "MAJ"}, "404": {"description": "Non trouvé"}}
      },
      "delete": {
        "tags": ["Projets"],
        "summary": "Supprimer un projet",
  "security": [{"adminJwt": []}],
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "responses": {"200": {"description": "Supprimé"}, "404": {"description": "Non trouvé"}}
      }
    },
    "/api/competences": {
      "get": {
        "tags": ["Compétences"],
        "summary": "Liste des compétences",
        "responses": {
          "200": {"description": "OK", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Competence"}}, "examples": {"exemple": {"value": [{"id":1,"nom":"TypeScript","logoPath":"/images-competences/ts.png","type":"langage"},{"id":2,"nom":"React","logoPath":"/images-competences/react.png","type":"framework"}]}}}}}
        }
      },
      "post": {
        "tags": ["Compétences"],
        "summary": "Créer une compétence",
  "security": [{"adminJwt": []}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CompetenceInput"}, "example": {"nom":"Rust","type":"langage","logoPath":"/images-competences/rust.png"}}}},
        "responses": {"201": {"description": "Créé"}, "400": {"description": "Données invalides"}}
      }
    },
    "/api/competences/{id}": {
      "get": {
        "tags": ["Compétences"],
        "summary": "Obtenir une compétence",
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Competence"}, "example": {"id":1,"nom":"TypeScript","logoPath":"/images-competences/ts.png","type":"langage"}}}}, "404": {"description": "Non trouvé"}}
      },
      "put": {
        "tags": ["Compétences"],
        "summary": "Mettre à jour une compétence",
  "security": [{"adminJwt": []}],
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CompetenceInput"}, "example": {"nom":"TypeScript 5","type":"langage","logoPath":"/images-competences/ts.png"}}}},
        "responses": {"200": {"description": "MAJ"}, "404": {"description": "Non trouvé"}}
      },
      "delete": {
        "tags": ["Compétences"],
        "summary": "Supprimer une compétence",
  "security": [{"adminJwt": []}],
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "integer"}}],
        "responses": {"200": {"description": "Supprimé"}, "404": {"description": "Non trouvé"}}
      }
    },
    "/api/upload/logo": {
      "post": {
        "tags": ["Uploads"],
        "summary": "Uploader un logo (multipart/form-data)",
  "security": [{"adminJwt": []}],
        "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"type": "object", "properties": {"file": {"type": "string", "format": "binary"}}, "required": ["file"]}}}},
        "responses": {"201": {"description": "Chemin retourné", "content": {"application/json": {"schema": {"type": "object", "properties": {"path": {"type": "string"}}}, "example": {"path": "/images-competences/1693742222-logo.png"}}}}, "413": {"description": "Fichier trop volumineux"}, "415": {"description": "Type non supporté"}}
      }
    },
    "/api/upload/image": {
      "post": {
        "tags": ["Uploads"],
        "summary": "Uploader une image de projet (multipart/form-data)",
  "security": [{"adminJwt": []}],
        "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"type": "object", "properties": {"file": {"type": "string", "format": "binary"}}, "required": ["file"]}}}},
        "responses": {"201": {"description": "Chemin retourné", "content": {"application/json": {"schema": {"type": "object", "properties": {"path": {"type": "string"}}}, "example": {"path": "/images-projets/1693742333-image.png"}}}}}
      }
    },
    "/api/tinymce-key": {
      "get": {
        "tags": ["TinyMCE"],
        "summary": "Vérifier si une clé TinyMCE existe côté serveur",
        "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"type": "object", "properties": {"exists": {"type": "boolean"}}}, "example": {"exists": true}}}}}
      },
  "post": {
        "tags": ["TinyMCE"],
        "summary": "Valider une clé TinyMCE (HEAD sur CDN)",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"key": {"type": "string"}}, "required": ["key"]}, "example": {"key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}}},
        "responses": {"200": {"description": "Valide", "content": {"application/json": {"schema": {"type": "object", "properties": {"valid": {"type": "boolean"}}}, "example": {"valid": true}}}}, "400": {"description": "Invalide"}, "500": {"description": "Erreur réseau"}}
      }
    }
  },
  "components": {
    "securitySchemes": {
      "adminJwt": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}
    },
    "schemas": {
      "Projet": {
        "type": "object",
        "properties": {
          "id": {"type": "integer"},
          "titre": {"type": "string"},
          "description": {"type": "string"},
          "date": {"type": "string"},
          "type": {"type": "string"},
          "url": {"type": "string", "nullable": true},
          "imagePath": {"type": "string", "nullable": true},
          "contenu": {"type": "string", "nullable": true}
        }
      },
      "ProjetInput": {
        "type": "object",
        "required": ["titre", "description", "date", "type"],
        "properties": {
          "titre": {"type": "string"},
          "description": {"type": "string"},
          "date": {"type": "string"},
          "type": {"type": "string"},
          "url": {"type": "string"},
          "imagePath": {"type": "string"},
          "contenu": {"type": "string"}
        }
      },
      "Competence": {
        "type": "object",
        "properties": {
          "id": {"type": "integer"},
          "nom": {"type": "string"},
          "logoPath": {"type": "string", "nullable": true},
          "type": {"type": "string"}
        }
      },
      "CompetenceInput": {
        "type": "object",
        "required": ["nom", "type"],
        "properties": {
          "nom": {"type": "string"},
          "logoPath": {"type": "string"},
          "type": {"type": "string"}
        }
      }
    }
  }
}
