{
  "openapi": "3.0.3",
  "info": {
    "title": "Nexus API",
    "version": "1.0.0",
    "description": "API REST del backend Nexus (enxu_back). Gestiona autenticación, perfiles de usuario, proyectos colaborativos y chat en tiempo real.\n\n## Autenticación\nUsa JWT Bearer Token. Obtén el token en `/auth/login` o `/auth/registrar` e inclúyelo en el header `Authorization: Bearer {token}`.\n\n## Formato de respuesta\nTodas las respuestas siguen el formato:\n```json\n{\n  \"success\": true|false,\n  \"message\": \"Descripción del resultado\",\n  \"data\": {} | [] | null\n}\n```"
  },
  "servers": [
    {
      "url": "http://localhost/enxu_back/public",
      "description": "Servidor local de desarrollo"
    }
  ],
  "tags": [
    { "name": "Root", "description": "Health check de la API" },
    { "name": "Auth", "description": "Autenticación: login, registro, social login, sesión y logout" },
    { "name": "Password", "description": "Recuperación y restablecimiento de contraseña" },
    { "name": "Perfil", "description": "Gestión del perfil personal del usuario" },
    { "name": "PerfilProfesional", "description": "Catálogo de perfiles profesionales (roles del sistema)" },
    { "name": "Ubicaciones", "description": "Catálogos geográficos: países, departamentos y ciudades" },
    { "name": "Proyectos", "description": "Gestión de proyectos, postulaciones y matching" },
    { "name": "Chat", "description": "Mensajería entre miembros de proyectos" }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Token JWT obtenido al autenticarse. Incluirlo como: `Authorization: Bearer {token}`"
      }
    },
    "schemas": {
      "ApiResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": true },
          "message": { "type": "string", "example": "Operación exitosa" },
          "data": {}
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": false },
          "message": { "type": "string", "example": "Descripción del error" }
        }
      },
      "Usuario": {
        "type": "object",
        "properties": {
          "usu_id": { "type": "integer", "example": 1 },
          "usu_email": { "type": "string", "format": "email", "example": "usuario@ejemplo.com" },
          "usu_estado": { "type": "integer", "enum": [0, 1], "example": 1, "description": "1=activo, 0=inactivo" },
          "usu_verificado": { "type": "integer", "enum": [0, 1], "example": 1 },
          "usu_metodo_verificacion": { "type": "string", "nullable": true, "example": "email" },
          "usu_ultimo_login": { "type": "string", "format": "date-time", "nullable": true },
          "creado_fecha": { "type": "string", "format": "date-time", "nullable": true },
          "actualizado_fecha": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "Perfil": {
        "type": "object",
        "properties": {
          "per_id": { "type": "integer", "example": 1 },
          "usu_id": { "type": "integer", "example": 1 },
          "per_nombres": { "type": "string", "nullable": true, "example": "Juan Carlos" },
          "per_ape_paterno": { "type": "string", "nullable": true, "example": "Rodríguez" },
          "per_ape_materno": { "type": "string", "nullable": true, "example": "López" },
          "per_genero": { "type": "string", "nullable": true, "example": "M" },
          "per_empresa": { "type": "string", "nullable": true, "example": "Tech Solutions S.A." },
          "ppf_id": { "type": "integer", "nullable": true, "example": 2 },
          "per_idioma": { "type": "string", "example": "es", "default": "es" },
          "per_tema": { "type": "string", "example": "claro", "enum": ["claro", "oscuro"], "default": "claro" },
          "per_titulo": { "type": "string", "nullable": true, "example": "Desarrollador Full Stack" },
          "per_descripcion": { "type": "string", "nullable": true, "example": "Desarrollador con 5 años de experiencia." },
          "per_remoto": { "type": "integer", "nullable": true, "example": 1 },
          "per_disponibilidad": { "type": "integer", "nullable": true, "example": 1 },
          "ciu_id": { "type": "integer", "nullable": true, "example": 5 },
          "creado_fecha": { "type": "string", "format": "date-time", "nullable": true },
          "actualizado_fecha": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "PerfilProfesional": {
        "type": "object",
        "properties": {
          "ppf_id": { "type": "integer", "example": 2 },
          "ppf_nombre": { "type": "string", "example": "Desarrollador Backend" },
          "ppf_descripcion": { "type": "string", "nullable": true, "example": "Especialista en servidor y APIs" },
          "ppf_estado": { "type": "integer", "enum": [0, 1], "example": 1 },
          "creado_por": { "type": "integer", "nullable": true },
          "creado_fecha": { "type": "string", "format": "date-time", "nullable": true },
          "actualizado_por": { "type": "integer", "nullable": true },
          "actualizado_fecha": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "Habilidad": {
        "type": "object",
        "properties": {
          "hab_id": { "type": "integer", "example": 1 },
          "hab_nombre": { "type": "string", "example": "PHP" },
          "hab_categoria": { "type": "string", "nullable": true, "example": "Backend" }
        }
      },
      "Proyecto": {
        "type": "object",
        "properties": {
          "pro_id": { "type": "integer", "example": 10 },
          "usu_id": { "type": "integer", "example": 1 },
          "pro_titulo": { "type": "string", "maxLength": 150, "example": "App de Delivery con React Native" },
          "pro_descripcion": { "type": "string", "example": "Desarrollo de una aplicación móvil de delivery." },
          "pro_ciudad_id": { "type": "integer", "nullable": true, "example": 1 },
          "pro_remoto": { "type": "boolean", "example": true },
          "pro_estado": { "type": "integer", "enum": [0, 1], "example": 1, "description": "1=activo, 0=anulado" },
          "pro_fecha_inicio": { "type": "string", "format": "date-time", "nullable": true },
          "pro_fecha_cierre": { "type": "string", "format": "date-time", "nullable": true },
          "creado_fecha": { "type": "string", "format": "date-time", "nullable": true },
          "actualizado_fecha": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "ProyectoPerfil": {
        "type": "object",
        "properties": {
          "prp_id": { "type": "integer", "example": 3 },
          "pro_id": { "type": "integer", "example": 10 },
          "ppf_id": { "type": "integer", "example": 1 },
          "prp_cupos": { "type": "integer", "minimum": 1, "example": 2 },
          "prp_cupos_ocupados": { "type": "integer", "example": 0 },
          "prp_estado": { "type": "integer", "enum": [0, 1], "example": 1 }
        }
      },
      "ProyectoPostulacion": {
        "type": "object",
        "properties": {
          "ppo_id": { "type": "integer", "example": 15 },
          "pro_id": { "type": "integer", "example": 10 },
          "usu_id": { "type": "integer", "example": 3 },
          "hab_id": { "type": "integer", "example": 5 },
          "ppo_estado": { "type": "integer", "enum": [1, 2, 3], "example": 1, "description": "1=pendiente, 2=aceptada, 3=rechazada" },
          "ppo_fecha": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "ProyectoConversacion": {
        "type": "object",
        "properties": {
          "pc_id": { "type": "integer", "example": 8 },
          "pro_id": { "type": "integer", "example": 10 },
          "creador_id": { "type": "integer", "example": 1 },
          "socio_id": { "type": "integer", "example": 3 },
          "pc_estado": { "type": "integer", "enum": [0, 1], "example": 1 }
        }
      },
      "ProyectoMensaje": {
        "type": "object",
        "properties": {
          "pm_id": { "type": "integer", "example": 25 },
          "pc_id": { "type": "integer", "example": 8 },
          "usu_id": { "type": "integer", "example": 1 },
          "pm_tipo": { "type": "string", "enum": ["texto", "imagen"], "example": "texto" },
          "pm_contenido": { "type": "string", "example": "¡Hola! ¿Cómo avanza el proyecto?" },
          "pm_fecha": { "type": "string", "format": "date-time", "example": "2025-03-12T22:45:00" }
        }
      },
      "Pais": {
        "type": "object",
        "properties": {
          "pai_id": { "type": "integer", "example": 1 },
          "pai_nombre": { "type": "string", "example": "Colombia" },
          "pai_codigo": { "type": "string", "example": "CO" }
        }
      },
      "Departamento": {
        "type": "object",
        "properties": {
          "dep_id": { "type": "integer", "example": 1 },
          "dep_nombre": { "type": "string", "example": "Antioquia" },
          "pai_id": { "type": "integer", "example": 1 }
        }
      },
      "Ciudad": {
        "type": "object",
        "properties": {
          "ciu_id": { "type": "integer", "example": 1 },
          "ciu_nombre": { "type": "string", "example": "Medellín" },
          "dep_id": { "type": "integer", "example": 1 }
        }
      },
      "DispositivoInfo": {
        "type": "object",
        "required": ["device_uuid"],
        "properties": {
          "device_uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440000" },
          "device_sistema": { "type": "string", "nullable": true, "example": "Android" },
          "device_modelo": { "type": "string", "nullable": true, "example": "Samsung Galaxy S21" }
        }
      },
      "AuthToken": {
        "type": "object",
        "properties": {
          "token": { "type": "string", "example": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." },
          "usuario": { "$ref": "#/components/schemas/Usuario" }
        }
      },
      "PerfilResumen": {
        "type": "object",
        "properties": {
          "usuario": {
            "type": "object",
            "properties": {
              "usu_id": { "type": "integer" },
              "email": { "type": "string" },
              "verificado": { "type": "boolean" }
            }
          },
          "perfil": {
            "type": "object",
            "properties": {
              "nombres_completos": { "type": "string", "nullable": true },
              "titulo_profesional": { "type": "string", "nullable": true },
              "descripcion": { "type": "string", "nullable": true },
              "ciudad_id": { "type": "integer", "nullable": true }
            }
          },
          "perfil_profesional": { "$ref": "#/components/schemas/PerfilProfesional" },
          "metricas": {
            "type": "object",
            "properties": {
              "proyectos_creados": { "type": "integer" },
              "proyectos_participa": { "type": "integer" },
              "total_conexiones": { "type": "integer" }
            }
          },
          "conexiones": { "type": "array", "items": {} },
          "habilidades": { "type": "array", "items": { "$ref": "#/components/schemas/Habilidad" } }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Token no proporcionado, inválido o expirado",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" },
            "example": { "success": false, "message": "Token inválido o expirado" }
          }
        }
      },
      "BadRequest": {
        "description": "Datos de la solicitud inválidos o incompletos",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" }
          }
        }
      },
      "NotFound": {
        "description": "Recurso no encontrado",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" },
            "example": { "success": false, "message": "Recurso no encontrado" }
          }
        }
      },
      "Forbidden": {
        "description": "Sin permisos para realizar la acción",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" },
            "example": { "success": false, "message": "No autorizado" }
          }
        }
      },
      "InternalError": {
        "description": "Error interno del servidor",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" },
            "example": { "success": false, "message": "Error interno del servidor" }
          }
        }
      }
    }
  },
  "paths": {
    "/": {
      "get": {
        "tags": ["Root"],
        "summary": "Health Check",
        "description": "Verifica que la API esté operativa. Retorna versión y entorno.",
        "responses": {
          "200": {
            "description": "API operativa",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiResponse" },
                "example": {
                  "success": true,
                  "message": "API Nexus funcionando correctamente",
                  "data": { "version": "v1", "entorno": "development" }
                }
              }
            }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login con email y contraseña",
        "description": "Autentica un usuario existente. Requiere email, contraseña y datos del dispositivo. Retorna un JWT.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email", "password", "device_uuid"],
                "properties": {
                  "email": { "type": "string", "format": "email", "example": "usuario@ejemplo.com" },
                  "password": { "type": "string", "format": "password", "example": "MiPassword123!" },
                  "device_uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440000" },
                  "device_sistema": { "type": "string", "nullable": true, "example": "Android" },
                  "device_modelo": { "type": "string", "nullable": true, "example": "Samsung Galaxy S21" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login exitoso",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiResponse" },
                "example": {
                  "success": true,
                  "message": "Login exitoso",
                  "data": { "token": "eyJ0eXAiOiJKV1Qi...", "usuario": { "usu_id": 1, "usu_email": "usuario@ejemplo.com" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/auth/registrar": {
      "post": {
        "tags": ["Auth"],
        "summary": "Registro de nuevo usuario",
        "description": "Crea un nuevo usuario en el sistema con email, contraseña y datos del dispositivo.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email", "password", "device_uuid"],
                "properties": {
                  "email": { "type": "string", "format": "email", "example": "nuevo@ejemplo.com" },
                  "password": { "type": "string", "format": "password", "minLength": 6, "example": "MiPassword123!" },
                  "device_uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440001" },
                  "device_sistema": { "type": "string", "nullable": true, "example": "iOS" },
                  "device_modelo": { "type": "string", "nullable": true, "example": "iPhone 13" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Usuario registrado exitosamente",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Usuario registrado exitosamente",
                  "data": { "token": "eyJ0eXAiOiJKV1Qi...", "usuario": { "usu_id": 42, "usu_email": "nuevo@ejemplo.com" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/auth/login-google": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login con Google OAuth",
        "description": "Autentica o registra un usuario mediante Google. Requiere el id_token proporcionado por Google Sign-In.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["id_token", "email", "device_uuid"],
                "properties": {
                  "id_token": { "type": "string", "example": "eyJhbGciOiJSUzI1NiIsImtpZCI6..." },
                  "email": { "type": "string", "format": "email", "example": "usuario@gmail.com" },
                  "device_uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440002" },
                  "device_sistema": { "type": "string", "nullable": true, "example": "Android" },
                  "device_modelo": { "type": "string", "nullable": true, "example": "Pixel 6" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login con Google exitoso",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Login con Google exitoso", "data": { "token": "eyJ...", "usuario": {} } }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/auth/login-facebook": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login con Facebook OAuth",
        "description": "Autentica o registra un usuario mediante Facebook. Requiere el access_token de Facebook.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["access_token", "email", "device_uuid"],
                "properties": {
                  "access_token": { "type": "string", "example": "EAABwzLixnjYBO..." },
                  "email": { "type": "string", "format": "email", "example": "usuario@facebook.com" },
                  "device_uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440003" },
                  "device_sistema": { "type": "string", "nullable": true },
                  "device_modelo": { "type": "string", "nullable": true }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login con Facebook exitoso",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Login con Facebook exitoso", "data": { "token": "eyJ..." } }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/auth/verificar-sesion": {
      "get": {
        "tags": ["Auth"],
        "summary": "Verificar sesión activa",
        "description": "Valida que el token JWT sea vigente y la sesión esté activa en base de datos.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Sesión válida",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Sesión válida", "data": { "usu_id": 1, "sesion_activa": true } }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "Cerrar sesión",
        "description": "Invalida el token JWT actual en base de datos. El token no podrá usarse después.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Logout exitoso",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Logout exitoso", "data": null }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/password/solicitar": {
      "post": {
        "tags": ["Password"],
        "summary": "Solicitar recuperación de contraseña",
        "description": "Envía un enlace de recuperación al email indicado. Por seguridad, siempre responde 202 aunque el email no exista.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email"],
                "properties": {
                  "email": { "type": "string", "format": "email", "example": "usuario@ejemplo.com" }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Solicitud procesada",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Se ha enviado un enlace de recuperación si el email existe", "data": null }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/password/validar": {
      "get": {
        "tags": ["Password"],
        "summary": "Validar token de recuperación",
        "description": "Verifica que el token de recuperación sea válido y no haya expirado.",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "description": "Token de recuperación recibido por email",
            "schema": { "type": "string", "example": "abc123tokenreset" }
          }
        ],
        "responses": {
          "200": {
            "description": "Token válido",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Token válido",
                  "data": { "token": "abc123tokenreset", "email": "usuario@ejemplo.com", "expira": "2025-03-13T23:59:59" }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/password/restablecer": {
      "post": {
        "tags": ["Password"],
        "summary": "Restablecer contraseña",
        "description": "Establece una nueva contraseña usando el token de recuperación. El token se invalida tras su uso.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["token", "password", "confirmacion"],
                "properties": {
                  "token": { "type": "string", "example": "abc123tokenreset" },
                  "password": { "type": "string", "format": "password", "example": "NuevaPassword123!" },
                  "confirmacion": { "type": "string", "format": "password", "example": "NuevaPassword123!" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contraseña restablecida",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Contraseña restablecida correctamente" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/perfil": {
      "post": {
        "tags": ["Perfil"],
        "summary": "Guardar o actualizar perfil personal",
        "description": "Crea el perfil si no existe, o lo actualiza si ya existe. Todos los campos son opcionales excepto la autenticación.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "per_nombres": { "type": "string", "example": "Juan Carlos" },
                  "per_ape_paterno": { "type": "string", "example": "Rodríguez" },
                  "per_ape_materno": { "type": "string", "example": "López" },
                  "per_genero": { "type": "string", "example": "M" },
                  "per_empresa": { "type": "string", "example": "Tech Solutions S.A." },
                  "ppf_id": { "type": "integer", "example": 2 },
                  "per_idioma": { "type": "string", "default": "es", "example": "es" },
                  "per_tema": { "type": "string", "enum": ["claro", "oscuro"], "default": "claro" },
                  "per_titulo": { "type": "string", "example": "Desarrollador Full Stack" },
                  "per_descripcion": { "type": "string", "example": "Desarrollador con 5 años de experiencia." },
                  "per_remoto": { "type": "integer", "example": 1 },
                  "per_disponibilidad": { "type": "integer", "example": 1 },
                  "ciu_id": { "type": "integer", "example": 5 }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Perfil actualizado exitosamente",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiResponse" }
              }
            }
          },
          "201": { "description": "Perfil creado exitosamente" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/perfil/resumen": {
      "get": {
        "tags": ["Perfil"],
        "summary": "Obtener resumen completo del perfil",
        "description": "Retorna datos del usuario, perfil personal, perfil profesional, métricas (proyectos, conexiones) y habilidades.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Resumen de perfil obtenido",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "$ref": "#/components/schemas/PerfilResumen" } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/perfil/habilidades": {
      "get": {
        "tags": ["Perfil"],
        "summary": "Listar habilidades del perfil",
        "description": "Retorna las habilidades asociadas al perfil profesional del usuario autenticado.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Habilidades obtenidas",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Habilidades obtenidas correctamente",
                  "data": [
                    { "hab_id": 1, "hab_nombre": "PHP", "hab_categoria": "Backend" },
                    { "hab_id": 5, "hab_nombre": "JavaScript", "hab_categoria": "Frontend" }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      },
      "put": {
        "tags": ["Perfil"],
        "summary": "Actualizar habilidades del perfil",
        "description": "Reemplaza completamente las habilidades del perfil del usuario con el nuevo conjunto.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "habilidades": {
                    "type": "array",
                    "items": { "type": "integer" },
                    "example": [1, 3, 5, 8]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Habilidades actualizadas",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Habilidades actualizadas correctamente",
                  "data": [{ "hab_id": 1, "hab_nombre": "PHP" }]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/perfil-profesional": {
      "get": {
        "tags": ["PerfilProfesional"],
        "summary": "Listar perfiles profesionales",
        "description": "Retorna el catálogo de perfiles profesionales disponibles. Soporta filtros.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "description": "Filtrar por estado: 1=activo, 0=inactivo",
            "schema": { "type": "integer", "enum": [0, 1], "example": 1 }
          },
          {
            "name": "buscar",
            "in": "query",
            "required": false,
            "description": "Búsqueda por nombre del perfil profesional",
            "schema": { "type": "string", "example": "desarrollador" }
          }
        ],
        "responses": {
          "200": {
            "description": "Perfiles profesionales obtenidos",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/PerfilProfesional" } } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      },
      "post": {
        "tags": ["PerfilProfesional"],
        "summary": "Crear perfil profesional",
        "description": "Registra un nuevo tipo de perfil profesional en el sistema.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["ppf_nombre"],
                "properties": {
                  "ppf_nombre": { "type": "string", "example": "Desarrollador Mobile" },
                  "ppf_descripcion": { "type": "string", "nullable": true, "example": "Especialista en apps iOS y Android" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Perfil profesional creado",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PerfilProfesional" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/perfil-profesional/{ppf_id}": {
      "put": {
        "tags": ["PerfilProfesional"],
        "summary": "Actualizar perfil profesional",
        "description": "Actualiza nombre y/o descripción de un perfil profesional existente.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "ppf_id",
            "in": "path",
            "required": true,
            "description": "ID del perfil profesional a actualizar",
            "schema": { "type": "integer", "example": 5 }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ppf_nombre": { "type": "string", "example": "Desarrollador Mobile Senior" },
                  "ppf_descripcion": { "type": "string", "example": "Especialista senior en React Native y Flutter" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Perfil profesional actualizado",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PerfilProfesional" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/ubicaciones/paises": {
      "get": {
        "tags": ["Ubicaciones"],
        "summary": "Listar países",
        "description": "Retorna todos los países disponibles en el catálogo. No requiere autenticación.",
        "responses": {
          "200": {
            "description": "Lista de países",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Pais" } } } }
                  ]
                }
              }
            }
          },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/ubicaciones/paises/{paisId}/departamentos": {
      "get": {
        "tags": ["Ubicaciones"],
        "summary": "Listar departamentos de un país",
        "description": "Retorna todos los departamentos/estados del país indicado.",
        "parameters": [
          {
            "name": "paisId",
            "in": "path",
            "required": true,
            "description": "ID del país",
            "schema": { "type": "integer", "example": 1 }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de departamentos",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Departamento" } } } }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/ubicaciones/departamentos/{depId}/ciudades": {
      "get": {
        "tags": ["Ubicaciones"],
        "summary": "Listar ciudades de un departamento",
        "description": "Retorna todas las ciudades/municipios del departamento indicado.",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "description": "ID del departamento",
            "schema": { "type": "integer", "example": 1 }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de ciudades",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Ciudad" } } } }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/proyectos": {
      "post": {
        "tags": ["Proyectos"],
        "summary": "Crear proyecto",
        "description": "Crea un nuevo proyecto. Se deben definir perfiles profesionales requeridos con habilidades y cupos. Opcionalmente se pueden añadir socios iniciales.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["titulo", "descripcion", "perfiles"],
                "properties": {
                  "titulo": { "type": "string", "maxLength": 150, "example": "App de Delivery con React Native" },
                  "descripcion": { "type": "string", "example": "Desarrollo de una aplicación móvil de delivery." },
                  "ciudad_id": { "type": "integer", "nullable": true, "example": 1 },
                  "remoto": { "type": "boolean", "default": false, "example": true },
                  "perfiles": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "required": ["ppf_id", "cupos", "habilidades_requeridas"],
                      "properties": {
                        "ppf_id": { "type": "integer", "example": 1 },
                        "cupos": { "type": "integer", "minimum": 1, "example": 2 },
                        "habilidades_requeridas": { "type": "array", "items": { "type": "integer" }, "example": [5, 9] }
                      }
                    }
                  },
                  "socios": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": ["usu_id", "hab_id"],
                      "properties": {
                        "usu_id": { "type": "integer", "example": 7 },
                        "hab_id": { "type": "integer", "example": 5 }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proyecto creado exitosamente",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Proyecto creado exitosamente",
                  "data": { "proyecto_id": 10, "proyecto": {}, "perfiles": [], "socios": [] }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      },
      "get": {
        "tags": ["Proyectos"],
        "summary": "Listar mis proyectos",
        "description": "Lista todos los proyectos creados por el usuario autenticado.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Lista de proyectos del usuario",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Proyecto" } } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/proyectos/obtener": {
      "get": {
        "tags": ["Proyectos"],
        "summary": "Obtener proyecto por ID",
        "description": "Retorna el detalle de un proyecto específico del usuario autenticado.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "ID del proyecto",
            "schema": { "type": "integer", "example": 10 }
          }
        ],
        "responses": {
          "200": {
            "description": "Proyecto obtenido",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "$ref": "#/components/schemas/Proyecto" } } }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/proyectos/actualizar": {
      "put": {
        "tags": ["Proyectos"],
        "summary": "Actualizar proyecto",
        "description": "Actualiza los datos de un proyecto del usuario autenticado. Solo el propietario puede actualizar.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "ID del proyecto a actualizar",
            "schema": { "type": "integer", "example": 10 }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "titulo": { "type": "string", "maxLength": 150 },
                  "descripcion": { "type": "string" },
                  "ciudad_id": { "type": "integer", "nullable": true },
                  "remoto": { "type": "boolean" },
                  "fecha_inicio": { "type": "string", "format": "date" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Proyecto actualizado" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/proyectos/eliminar": {
      "delete": {
        "tags": ["Proyectos"],
        "summary": "Anular proyecto (soft-delete)",
        "description": "Marca el proyecto como inactivo (estado=0). Solo el propietario puede anularlo.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "ID del proyecto a anular",
            "schema": { "type": "integer", "example": 10 }
          }
        ],
        "responses": {
          "200": {
            "description": "Proyecto anulado",
            "content": {
              "application/json": {
                "example": { "success": true, "message": "Proyecto anulado exitosamente", "data": { "proyecto_id": 10, "estado": 0 } }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/proyectos/postular": {
      "post": {
        "tags": ["Proyectos"],
        "summary": "Postularse a un proyecto",
        "description": "Registra la postulación del usuario a un proyecto. El perfil profesional del usuario debe coincidir con algún perfil del proyecto. La habilidad debe estar en el perfil del usuario.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["proyecto_id", "hab_id"],
                "properties": {
                  "proyecto_id": { "type": "integer", "example": 10 },
                  "hab_id": { "type": "integer", "example": 5 }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Postulación registrada",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Postulación registrada correctamente",
                  "data": { "postulacion_id": 15, "proyecto_id": 10, "cupos_disponibles": 1 }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/proyectos/postulaciones": {
      "get": {
        "tags": ["Proyectos"],
        "summary": "Listar postulaciones recibidas",
        "description": "Lista las postulaciones recibidas en los proyectos del usuario autenticado (como dueño del proyecto).",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "proyecto_id",
            "in": "query",
            "required": false,
            "description": "Filtrar por proyecto específico",
            "schema": { "type": "integer", "example": 10 }
          },
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "description": "Estado de postulación: 1=pendiente, 2=aceptada, 3=rechazada",
            "schema": { "type": "integer", "enum": [1, 2, 3], "example": 1 }
          }
        ],
        "responses": {
          "200": { "description": "Postulaciones obtenidas" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/proyectos/postulaciones/gestionar": {
      "post": {
        "tags": ["Proyectos"],
        "summary": "Aceptar o rechazar postulación",
        "description": "El propietario del proyecto acepta o rechaza una postulación. Al aceptar: se crea el miembro, se reserva cupo y se crea la conversación de chat.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["postulacion_id", "accion"],
                "properties": {
                  "postulacion_id": { "type": "integer", "example": 15 },
                  "accion": { "type": "string", "enum": ["aceptar", "rechazar"], "example": "aceptar" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Postulación gestionada" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/chat/conversaciones": {
      "get": {
        "tags": ["Chat"],
        "summary": "Listar conversaciones",
        "description": "Lista todas las conversaciones del usuario autenticado (como creador de proyecto o como socio). Retorna el total y mensajes contextualizados cuando la lista está vacía.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Conversaciones obtenidas",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiResponse" },
                "examples": {
                  "conConversaciones": {
                    "summary": "Listado con resultados",
                    "value": {
                      "success": true,
                      "message": "Conversaciones obtenidas correctamente",
                      "data": {
                        "total": 1,
                        "conversaciones": [
                          {
                            "pc_id": 8,
                            "pro_id": 10,
                            "creador_id": 1,
                            "socio_id": 3,
                            "pc_estado": 1,
                            "proyecto": { "pro_titulo": "App de Delivery" }
                          }
                        ]
                      }
                    }
                  },
                  "sinConversaciones": {
                    "summary": "Usuario sin conversaciones",
                    "value": {
                      "success": true,
                      "message": "Aún no tienes conversaciones disponibles",
                      "data": {
                        "total": 0,
                        "conversaciones": []
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/proyectos/compatibles": {
      "get": {
        "tags": ["Proyectos"],
        "summary": "Listar proyectos compatibles (matching)",
        "description": "Retorna proyectos con perfil y habilidades compatibles con el usuario autenticado. Soporta paginación.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "description": "Cantidad de resultados por página",
            "schema": { "type": "integer", "example": 10 }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Desplazamiento para paginación",
            "schema": { "type": "integer", "example": 0 }
          },
          {
            "name": "pagina",
            "in": "query",
            "required": false,
            "description": "Número de página",
            "schema": { "type": "integer", "example": 1 }
          }
        ],
        "responses": {
          "200": { "description": "Proyectos compatibles obtenidos" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
            "description": "Cantidad de mensajes (default: 50)",
            "schema": { "type": "integer", "default": 50, "example": 50 }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Desplazamiento para paginación (default: 0)",
            "schema": { "type": "integer", "default": 0, "example": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "Mensajes obtenidos",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Mensajes obtenidos correctamente",
                  "data": { "conversacion_id": 8, "mensajes": [] }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/chat/mensajes/texto": {
      "post": {
        "tags": ["Chat"],
        "summary": "Enviar mensaje de texto",
        "description": "Envía un mensaje de texto en una conversación. El usuario debe ser participante.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["conversacion_id", "contenido"],
                "properties": {
                  "conversacion_id": { "type": "integer", "example": 8 },
                  "contenido": { "type": "string", "minLength": 1, "example": "¡Hola! ¿Cómo avanza el proyecto?" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mensaje enviado",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiResponse" },
                    { "properties": { "data": { "$ref": "#/components/schemas/ProyectoMensaje" } } }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/chat/mensajes/imagen": {
      "post": {
        "tags": ["Chat"],
        "summary": "Enviar mensaje de imagen",
        "description": "Envía un archivo de imagen en una conversación. Usar `multipart/form-data`. El campo de archivo se llama `archivo`.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["conversacion_id", "archivo"],
                "properties": {
                  "conversacion_id": { "type": "integer", "example": 8 },
                  "archivo": { "type": "string", "format": "binary", "description": "Archivo de imagen (JPG, PNG, GIF, etc.)" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Imagen enviada",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "message": "Imagen enviada correctamente",
                  "data": { "pm_id": 26, "pm_tipo": "imagen", "adjunto": { "url": "https://...", "nombre": "image.jpg" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    }
  }
}
