const serverUrl = process.env.NEXT_PUBLIC_ADMIN_URL || "http://localhost:3002";

const jsonContent = (schema: Record<string, unknown>, example?: unknown) => ({
  "application/json": {
    schema,
    ...(example === undefined ? {} : { example }),
  },
});

const successSchema = (dataSchema: Record<string, unknown>) => ({
  type: "object",
  additionalProperties: false,
  required: ["success", "data"],
  properties: {
    success: {
      type: "boolean",
      const: true,
    },
    data: dataSchema,
  },
});

const successResponse = (
  description: string,
  dataSchema: Record<string, unknown>,
  example: unknown,
  includeRateLimitHeaders = false
) => ({
  description,
  ...(includeRateLimitHeaders
    ? {
        headers: {
          "X-RateLimit-Limit-IP": {
            description: "Limite por IP para a janela atual.",
            schema: { type: "string", example: "120" },
          },
          "X-RateLimit-Limit-User": {
            description: "Limite por usuario autenticado para a janela atual.",
            schema: { type: "string", example: "120" },
          },
          "X-RateLimit-Remaining": {
            description: "Quantidade restante de requisicoes na janela atual.",
            schema: { type: "string", example: "119" },
          },
          "X-RateLimit-Reset": {
            description: "Unix timestamp em segundos de quando a janela sera reiniciada.",
            schema: { type: "string", example: "1763628292" },
          },
          "Retry-After": {
            description: "Segundos restantes para resetar a janela quando o limite for excedido.",
            schema: { type: "string", example: "60" },
          },
        },
      }
    : {}),
  content: jsonContent(successSchema(dataSchema), {
    success: true,
    data: example,
  }),
});

const errorResponse = (
  description: string,
  _status: number,
  code: string,
  message: string,
  details: unknown = null,
  includeRateLimitHeaders = false
) => ({
  description,
  ...(includeRateLimitHeaders
    ? {
        headers: {
          "Retry-After": {
            description: "Segundos para nova tentativa apos exceder o rate limit.",
            schema: { type: "string", example: "60" },
          },
          "X-RateLimit-Reset": {
            description: "Unix timestamp em segundos de quando a janela sera reiniciada.",
            schema: { type: "string", example: "1763628292" },
          },
        },
      }
    : {}),
  content: jsonContent(
    {
      $ref: "#/components/schemas/ErrorEnvelope",
    },
    {
      success: false,
      error: {
        code,
        message,
        details,
      },
    }
  ),
});

const companyScopeHeaderParameter = {
  name: "x-ktalogu-company-id",
  in: "header",
  required: false,
  description:
    "Empresa alvo da requisicao. Quando enviado, deve corresponder exatamente a empresa resolvida pelo token. Se divergir, a API retorna `403 cross_company_access_denied`.",
  schema: {
    type: "string",
    format: "uuid",
    example: "11111111-1111-4111-8111-111111111111",
  },
};

const idPathParameter = (name: string, label: string) => ({
  name,
  in: "path",
  required: true,
  description: `${label} em formato UUID.`,
  schema: {
    type: "string",
    format: "uuid",
    example: "11111111-1111-4111-8111-111111111111",
  },
});

export const apiV1OpenApiDocument = {
  openapi: "3.1.0",
  info: {
    title: "Ktalogu API",
    version: "1.0.0",
    description:
      "Camada versionada de integracao externa da Ktalogu. Todas as respostas funcionais da `/api/v1` usam envelope padrao `{ success, data }` para sucesso e `{ success, error }` para falha. A rota `/api/v1/openapi` e a excecao intencional e retorna o documento OpenAPI puro para compatibilidade com Swagger e ferramentas externas.",
  },
  servers: [
    {
      url: serverUrl,
      description: "Servidor administrativo local ou publicado da Ktalogu.",
    },
  ],
  components: {
    securitySchemes: {
      bearerAuth: {
        type: "http",
        scheme: "bearer",
        bearerFormat: "JWT",
        description: "Use o access token JWT retornado em `/api/v1/auth/login` ou `/api/v1/auth/refresh`.",
      },
    },
    schemas: {
      ErrorEnvelope: {
        type: "object",
        additionalProperties: false,
        required: ["success", "error"],
        properties: {
          success: {
            type: "boolean",
            const: false,
          },
          error: {
            type: "object",
            additionalProperties: false,
            required: ["code", "message", "details"],
            properties: {
              code: {
                type: "string",
                example: "missing_bearer_token",
              },
              message: {
                type: "string",
                example: "Token Bearer obrigatorio.",
              },
              details: {
                nullable: true,
                example: null,
              },
            },
          },
        },
      },
      HealthData: {
        type: "object",
        additionalProperties: false,
        required: ["version", "service", "timestamp"],
        properties: {
          version: { type: "string", example: "v1" },
          service: { type: "string", example: "ktalogu-api" },
          timestamp: { type: "string", format: "date-time", example: "2026-06-21T18:32:10.111Z" },
        },
      },
      UserSummary: {
        type: "object",
        additionalProperties: false,
        required: ["id", "email"],
        properties: {
          id: { type: "string", format: "uuid", example: "8a33f8f4-6b8d-4ab3-9a90-2b4f5f34a999" },
          email: { type: "string", nullable: true, example: "owner@empresa.com" },
        },
      },
      CompanyAuthContext: {
        type: "object",
        additionalProperties: false,
        required: ["id", "owner_id", "tenant_ids", "permissions"],
        properties: {
          id: { type: "string", format: "uuid", example: "11111111-1111-4111-8111-111111111111" },
          owner_id: { type: "string", nullable: true, format: "uuid", example: "22222222-2222-4222-8222-222222222222" },
          tenant_ids: {
            type: "array",
            items: { type: "string", format: "uuid" },
            example: [
              "11111111-1111-4111-8111-111111111111",
              "22222222-2222-4222-8222-222222222222",
            ],
          },
          permissions: {
            type: "array",
            items: { type: "string" },
            example: ["products.read", "categories.write", "quotes.write", "financial.read"],
          },
        },
      },
      SessionPayload: {
        type: "object",
        additionalProperties: false,
        required: ["access_token", "refresh_token", "token_type", "expires_at", "user", "company"],
        properties: {
          access_token: { type: "string", example: "eyJhbGciOi..." },
          refresh_token: { type: "string", example: "refresh-token-exemplo" },
          token_type: { type: "string", example: "bearer" },
          expires_at: { type: "integer", nullable: true, example: 1763630112 },
          user: { $ref: "#/components/schemas/UserSummary" },
          company: { $ref: "#/components/schemas/CompanyAuthContext" },
        },
      },
      AuthMeData: {
        type: "object",
        additionalProperties: false,
        required: ["user", "company"],
        properties: {
          user: { $ref: "#/components/schemas/UserSummary" },
          company: { $ref: "#/components/schemas/CompanyAuthContext" },
        },
      },
      LoginRequest: {
        type: "object",
        additionalProperties: false,
        required: ["email", "password"],
        properties: {
          email: { type: "string", format: "email", example: "owner@empresa.com" },
          password: { type: "string", minLength: 1, example: "minha-senha-segura" },
        },
      },
      RefreshRequest: {
        type: "object",
        additionalProperties: false,
        required: ["refresh_token"],
        properties: {
          refresh_token: { type: "string", minLength: 1, example: "refresh-token-exemplo" },
        },
      },
      LogoutRequest: {
        type: "object",
        additionalProperties: false,
        required: ["refresh_token"],
        properties: {
          refresh_token: { type: "string", minLength: 1, example: "refresh-token-exemplo" },
        },
      },
      CompanyProfile: {
        type: "object",
        additionalProperties: false,
        required: [
          "id",
          "profile_id",
          "name",
          "owner_id",
          "store_name",
          "logo_url",
          "cnpj",
          "phone",
          "company_whatsapp",
          "address_zip",
          "address_street",
          "address_number",
          "address_complement",
          "address_neighborhood",
          "address_city",
          "address_state",
          "address",
        ],
        properties: {
          id: { type: "string", format: "uuid", example: "11111111-1111-4111-8111-111111111111" },
          profile_id: { type: "string", format: "uuid", example: "22222222-2222-4222-8222-222222222222" },
          name: { type: "string", nullable: true, example: "Loja Exemplo" },
          owner_id: { type: "string", nullable: true, format: "uuid", example: "22222222-2222-4222-8222-222222222222" },
          store_name: { type: "string", example: "Loja Exemplo" },
          logo_url: { type: "string", example: "https://cdn.ktalogu.com/logo.png" },
          cnpj: { type: "string", example: "12.345.678/0001-99" },
          phone: { type: "string", example: "+55 11 4002-8922" },
          company_whatsapp: { type: "string", example: "+55 11 99999-0000" },
          address_zip: { type: "string", example: "01310-100" },
          address_street: { type: "string", example: "Avenida Paulista" },
          address_number: { type: "string", example: "1000" },
          address_complement: { type: "string", example: "10 andar" },
          address_neighborhood: { type: "string", example: "Bela Vista" },
          address_city: { type: "string", example: "Sao Paulo" },
          address_state: { type: "string", example: "SP" },
          address: { type: "string", example: "Avenida Paulista, 1000 - Bela Vista - Sao Paulo/SP" },
        },
      },
      CompanyUpdateRequest: {
        type: "object",
        additionalProperties: false,
        properties: {
          logo_url: { type: "string", example: "https://cdn.ktalogu.com/logo.png" },
          store_name: { type: "string", example: "Loja Exemplo" },
          cnpj: { type: "string", example: "12.345.678/0001-99" },
          phone: { type: "string", example: "+55 11 4002-8922" },
          company_whatsapp: { type: "string", example: "+55 11 99999-0000" },
          address_zip: { type: "string", example: "01310-100" },
          address_street: { type: "string", example: "Avenida Paulista" },
          address_number: { type: "string", example: "1000" },
          address_complement: { type: "string", example: "10 andar" },
          address_neighborhood: { type: "string", example: "Bela Vista" },
          address_city: { type: "string", example: "Sao Paulo" },
          address_state: { type: "string", example: "SP" },
          address: { type: "string", example: "Avenida Paulista, 1000 - Bela Vista - Sao Paulo/SP" },
        },
      },
      Category: {
        type: "object",
        additionalProperties: false,
        required: ["id", "name", "slug", "pricing_rule", "is_visible", "parent_id"],
        properties: {
          id: { type: "string", format: "uuid", example: "33333333-3333-4333-8333-333333333333" },
          name: { type: "string", example: "Canecas" },
          slug: { type: "string", example: "canecas" },
          pricing_rule: {
            type: "object",
            example: {
              marginTargetPct: 50,
              marginMinPct: 35,
              rounding: {
                type: "END_WITH",
                cents: 90,
              },
            },
          },
          is_visible: { type: "boolean", example: true },
          parent_id: {
            type: "string",
            nullable: true,
            format: "uuid",
            example: null,
          },
        },
      },
      CategoryListData: {
        type: "object",
        additionalProperties: false,
        required: ["items"],
        properties: {
          items: {
            type: "array",
            items: { $ref: "#/components/schemas/Category" },
          },
        },
      },
      CategoryWriteRequest: {
        type: "object",
        additionalProperties: false,
        properties: {
          name: { type: "string", example: "Canecas Personalizadas" },
          slug: { type: "string", example: "canecas-personalizadas" },
          pricing_rule: {
            type: "object",
            example: {
              marginTargetPct: 50,
              marginMinPct: 35,
              rounding: {
                type: "END_WITH",
                cents: 90,
              },
            },
          },
          is_visible: { type: "boolean", example: true },
          parent_id: {
            oneOf: [
              { type: "string", format: "uuid", example: "44444444-4444-4444-8444-444444444444" },
              { type: "null" },
            ],
          },
        },
      },
      UpdateAck: {
        type: "object",
        additionalProperties: false,
        required: ["updated"],
        properties: {
          updated: { type: "boolean", example: true },
        },
      },
      DeleteAck: {
        type: "object",
        additionalProperties: false,
        required: ["deleted"],
        properties: {
          deleted: { type: "boolean", example: true },
        },
      },
      ProductCategory: {
        type: "object",
        nullable: true,
        additionalProperties: false,
        required: ["id", "name", "slug"],
        properties: {
          id: { type: "string", format: "uuid", example: "33333333-3333-4333-8333-333333333333" },
          name: { type: "string", example: "Canecas" },
          slug: { type: "string", example: "canecas" },
        },
      },
      ProductImage: {
        type: "object",
        additionalProperties: false,
        required: ["image_url", "sort_order"],
        properties: {
          image_url: { type: "string", example: "https://cdn.ktalogu.com/produtos/caneca-1.png" },
          sort_order: { type: "integer", example: 0 },
        },
      },
      Product: {
        type: "object",
        additionalProperties: false,
        required: [
          "id",
          "name",
          "description",
          "price",
          "category_id",
          "category",
          "active",
          "image_url",
          "images",
          "mockups",
          "files",
        ],
        properties: {
          id: { type: "string", format: "uuid", example: "55555555-5555-4555-8555-555555555555" },
          name: { type: "string", example: "Caneca Branca 325ml" },
          description: { type: "string", example: "Caneca de ceramica pronta para sublimacao." },
          price: { type: "number", example: 39.9 },
          category_id: { type: "string", nullable: true, format: "uuid", example: "33333333-3333-4333-8333-333333333333" },
          category: { $ref: "#/components/schemas/ProductCategory" },
          active: { type: "boolean", example: true },
          image_url: { type: "string", nullable: true, example: "https://cdn.ktalogu.com/produtos/caneca-capa.png" },
          images: {
            type: "array",
            items: { $ref: "#/components/schemas/ProductImage" },
          },
          mockups: {
            type: "array",
            items: {},
            example: [],
          },
          files: {
            type: "array",
            items: {},
            example: [],
          },
        },
      },
      ProductListData: {
        type: "object",
        additionalProperties: false,
        required: ["items", "pagination"],
        properties: {
          items: {
            type: "array",
            items: { $ref: "#/components/schemas/Product" },
          },
          pagination: {
            type: "object",
            additionalProperties: false,
            required: ["page", "per_page", "total"],
            properties: {
              page: { type: "integer", example: 1 },
              per_page: { type: "integer", example: 20 },
              total: { type: "integer", example: 1 },
            },
          },
        },
      },
      ExtensionCustomer: {
        type: "object",
        nullable: true,
        additionalProperties: false,
        required: [
          "id",
          "name",
          "company_name",
          "type",
          "email",
          "phone",
          "whatsapp",
          "notes",
          "tags",
          "active",
          "created_at",
          "updated_at",
        ],
        properties: {
          id: { type: "string", format: "uuid", example: "99999999-9999-4999-8999-999999999999" },
          name: { type: "string", example: "Maria Silva" },
          company_name: { type: "string", nullable: true, example: "Loja Exemplo" },
          type: { type: "string", nullable: true, example: "pj" },
          email: { type: "string", nullable: true, example: "maria@empresa.com" },
          phone: { type: "string", nullable: true, example: "+55 11 4002-8922" },
          whatsapp: { type: "string", nullable: true, example: "+55 11 99999-9999" },
          notes: { type: "string", nullable: true, example: "Cliente recorrente de brindes corporativos." },
          tags: {
            type: "array",
            items: { type: "string" },
            example: ["vip", "revenda"],
          },
          active: { type: "boolean", example: true },
          created_at: { type: "string", nullable: true, format: "date-time", example: "2026-05-10T12:00:00.000Z" },
          updated_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T18:00:00.000Z" },
        },
      },
      ExtensionOrderSummary: {
        type: "object",
        additionalProperties: false,
        required: [
          "id",
          "number",
          "status",
          "total_amount",
          "financial_status",
          "created_at",
          "updated_at",
          "quote_id",
          "quote_number",
          "quote_title",
        ],
        properties: {
          id: { type: "string", format: "uuid", example: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" },
          number: { type: "integer", example: 456 },
          status: { type: "string", example: "finished" },
          total_amount: { type: "number", example: 1890.5 },
          financial_status: { type: "string", nullable: true, example: "paid" },
          created_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-20T10:00:00.000Z" },
          updated_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-20T12:00:00.000Z" },
          quote_id: { type: "string", nullable: true, format: "uuid", example: "66666666-6666-4666-8666-666666666666" },
          quote_number: { type: "integer", nullable: true, example: 123 },
          quote_title: { type: "string", nullable: true, example: "Orcamento de brindes corporativos" },
        },
      },
      ExtensionCommercialStatus: {
        type: "object",
        additionalProperties: false,
        required: ["code", "label"],
        properties: {
          code: { type: "string", example: "customer" },
          label: { type: "string", example: "Cliente com compras" },
        },
      },
      ExtensionProductInsight: {
        type: "object",
        additionalProperties: false,
        required: ["product_id", "product_name", "quantity", "total_amount", "sources", "product"],
        properties: {
          product_id: { type: "string", nullable: true, format: "uuid", example: "55555555-5555-4555-8555-555555555555" },
          product_name: { type: "string", example: "Caneca Branca 325ml" },
          quantity: { type: "number", example: 120 },
          total_amount: { type: "number", example: 4788 },
          sources: {
            type: "array",
            items: { type: "string" },
            example: ["order", "quote"],
          },
          product: {
            oneOf: [{ $ref: "#/components/schemas/Product" }, { type: "null" }],
          },
        },
      },
      ExtensionCustomerCommercialStats: {
        type: "object",
        additionalProperties: false,
        required: [
          "orders_count",
          "quotes_count",
          "total_purchased",
          "average_ticket",
          "last_purchase_at",
          "last_quote_at",
          "last_interaction_at",
          "current_status",
        ],
        properties: {
          orders_count: { type: "integer", example: 12 },
          quotes_count: { type: "integer", example: 18 },
          total_purchased: { type: "number", example: 8450.9 },
          average_ticket: { type: "number", example: 704.24 },
          last_purchase_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-20T10:00:00.000Z" },
          last_quote_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T08:10:00.000Z" },
          last_interaction_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T08:10:00.000Z" },
          current_status: { $ref: "#/components/schemas/ExtensionCommercialStatus" },
        },
      },
      ExtensionCustomerContextData: {
        type: "object",
        additionalProperties: false,
        required: [
          "phone",
          "customer_found",
          "customer",
          "company",
          "recent_quotes",
          "recent_orders",
          "top_products",
          "commercial_stats",
        ],
        properties: {
          phone: { type: "string", example: "5511999999999" },
          customer_found: { type: "boolean", example: true },
          customer: { $ref: "#/components/schemas/ExtensionCustomer" },
          company: { $ref: "#/components/schemas/CompanyProfile" },
          recent_quotes: {
            type: "array",
            items: { $ref: "#/components/schemas/QuoteSummary" },
          },
          recent_orders: {
            type: "array",
            items: { $ref: "#/components/schemas/ExtensionOrderSummary" },
          },
          top_products: {
            type: "array",
            items: { $ref: "#/components/schemas/ExtensionProductInsight" },
          },
          commercial_stats: { $ref: "#/components/schemas/ExtensionCustomerCommercialStats" },
        },
      },
      ExtensionConversationProduct: {
        type: "object",
        additionalProperties: false,
        required: ["product_id", "interactions", "product", "product_name"],
        properties: {
          product_id: { type: "string", nullable: true, format: "uuid", example: "55555555-5555-4555-8555-555555555555" },
          product_name: { type: "string", example: "Caneca Branca 325ml" },
          interactions: {
            type: "object",
            additionalProperties: false,
            required: ["quantity", "total_amount", "sources"],
            properties: {
              quantity: { type: "number", example: 120 },
              total_amount: { type: "number", example: 4788 },
              sources: {
                type: "array",
                items: { type: "string" },
                example: ["order", "quote"],
              },
            },
          },
          product: {
            oneOf: [{ $ref: "#/components/schemas/Product" }, { type: "null" }],
          },
        },
      },
      ExtensionConversationHistory: {
        type: "object",
        additionalProperties: false,
        required: ["total_orders", "total_quotes", "total_purchased", "average_ticket", "latest_interaction_at", "top_products"],
        properties: {
          total_orders: { type: "integer", example: 12 },
          total_quotes: { type: "integer", example: 18 },
          total_purchased: { type: "number", example: 8450.9 },
          average_ticket: { type: "number", example: 704.24 },
          latest_interaction_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T08:10:00.000Z" },
          top_products: {
            type: "array",
            items: { $ref: "#/components/schemas/ExtensionProductInsight" },
          },
        },
      },
      ExtensionConversationSuggestions: {
        type: "object",
        additionalProperties: false,
        required: [
          "can_view_customer",
          "can_review_recent_quotes",
          "can_review_recent_orders",
          "can_suggest_products",
          "can_prepare_quote",
        ],
        properties: {
          can_view_customer: { type: "boolean", example: true },
          can_review_recent_quotes: { type: "boolean", example: true },
          can_review_recent_orders: { type: "boolean", example: true },
          can_suggest_products: { type: "boolean", example: true },
          can_prepare_quote: { type: "boolean", example: true },
        },
      },
      ExtensionConversationContextData: {
        type: "object",
        additionalProperties: false,
        required: [
          "phone",
          "customer_found",
          "customer",
          "recent_quotes",
          "recent_orders",
          "related_products",
          "commercial_history",
          "suggestions_available",
        ],
        properties: {
          phone: { type: "string", example: "5511999999999" },
          customer_found: { type: "boolean", example: true },
          customer: { $ref: "#/components/schemas/ExtensionCustomer" },
          recent_quotes: {
            type: "array",
            items: { $ref: "#/components/schemas/QuoteSummary" },
          },
          recent_orders: {
            type: "array",
            items: { $ref: "#/components/schemas/ExtensionOrderSummary" },
          },
          related_products: {
            type: "array",
            items: { $ref: "#/components/schemas/ExtensionConversationProduct" },
          },
          commercial_history: { $ref: "#/components/schemas/ExtensionConversationHistory" },
          suggestions_available: { $ref: "#/components/schemas/ExtensionConversationSuggestions" },
        },
      },
      QuoteSummary: {
        type: "object",
        additionalProperties: false,
        required: ["id", "number", "status", "total", "created_at", "updated_at", "client_name"],
        properties: {
          id: { type: "string", format: "uuid", example: "66666666-6666-4666-8666-666666666666" },
          number: { type: "integer", example: 123 },
          status: { type: "string", example: "draft" },
          total: { type: "number", example: 149.9 },
          created_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T17:30:00.000Z" },
          updated_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-21T17:30:00.000Z" },
          client_name: { type: "string", nullable: true, example: "Empresa XPTO" },
        },
      },
      QuoteListData: {
        type: "object",
        additionalProperties: false,
        required: ["items"],
        properties: {
          items: {
            type: "array",
            items: { $ref: "#/components/schemas/QuoteSummary" },
          },
        },
      },
      QuoteItemInput: {
        type: "object",
        additionalProperties: false,
        required: ["title", "quantity", "unit_price"],
        properties: {
          id: { type: "string", format: "uuid", example: "77777777-7777-4777-8777-777777777777" },
          product_id: { type: "string", nullable: true, format: "uuid", example: "55555555-5555-4555-8555-555555555555" },
          unit_type: { type: "string", example: "unit" },
          width_m: { type: "number", nullable: true, example: null },
          height_m: { type: "number", nullable: true, example: null },
          length_m: { type: "number", nullable: true, example: null },
          title: { type: "string", example: "Caneca Branca 325ml" },
          description: { type: "string", nullable: true, example: "Arte incluida" },
          quantity: { type: "number", example: 10 },
          unit_price: { type: "number", example: 14.99 },
          unit_cost: { type: "number", example: 8.25 },
          selected_options: {
            type: "object",
            nullable: true,
            example: {
              cor_alca: "preta",
            },
          },
        },
      },
      QuoteAllocationInput: {
        type: "object",
        additionalProperties: false,
        required: ["seller_user_id", "allocation_percent"],
        properties: {
          seller_user_id: { type: "string", format: "uuid", example: "88888888-8888-4888-8888-888888888888" },
          allocation_percent: { type: "number", example: 60 },
          is_primary: { type: "boolean", example: true },
        },
      },
      QuoteCreateRequest: {
        type: "object",
        additionalProperties: false,
        required: ["client_id", "items"],
        properties: {
          client_id: { type: "string", format: "uuid", example: "99999999-9999-4999-8999-999999999999" },
          quick_quote: { type: "boolean", example: false },
          title: { type: "string", example: "Orcamento de brindes corporativos" },
          status: { type: "string", example: "draft" },
          expires_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-30T23:59:59.000Z" },
          delivery_date: { type: "string", nullable: true, format: "date-time", example: "2026-07-10T12:00:00.000Z" },
          notes: { type: "string", example: "Entrega no escritorio do cliente." },
          internal_notes: { type: "string", example: "Cliente VIP." },
          discount: { type: "number", example: 20 },
          shipping: { type: "number", example: 15 },
          shipping_details: {
            type: "object",
            nullable: true,
            example: {
              carrier: "Correios",
              service: "SEDEX",
            },
          },
          list_price_mode: { type: "boolean", example: false },
          seller_mode: { type: "string", enum: ["single", "split"], example: "single" },
          primary_seller_user_id: {
            type: "string",
            format: "uuid",
            example: "88888888-8888-4888-8888-888888888888",
          },
          allocations: {
            type: "array",
            items: { $ref: "#/components/schemas/QuoteAllocationInput" },
          },
          items: {
            type: "array",
            minItems: 1,
            items: { $ref: "#/components/schemas/QuoteItemInput" },
          },
        },
      },
      QuoteCreateData: {
        type: "object",
        additionalProperties: false,
        required: ["quote_id", "quote_number", "total", "expires_at", "share_url"],
        properties: {
          quote_id: { type: "string", format: "uuid", example: "66666666-6666-4666-8666-666666666666" },
          quote_number: { type: "integer", example: 123 },
          total: { type: "number", example: 149.9 },
          expires_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-30T23:59:59.000Z" },
          share_url: {
            type: "string",
            example: "http://localhost:3001/minha-loja/o/3f7d8f8fd0a0c0b0ab12cd34ef56ab78",
          },
        },
      },
      QuoteApprovalNotification: {
        type: "object",
        nullable: true,
        additionalProperties: false,
        required: ["clientName", "whatsapp", "whatsappNotify", "orderNumber", "quoteNumber", "status"],
        properties: {
          clientName: { type: "string", example: "Empresa XPTO" },
          whatsapp: { type: "string", example: "+55 11 99999-0000" },
          whatsappNotify: { type: "boolean", example: true },
          orderNumber: { type: "integer", nullable: true, example: 456 },
          quoteNumber: { type: "integer", nullable: true, example: 123 },
          status: { type: "string", example: "approved" },
        },
      },
      QuoteApprovalData: {
        type: "object",
        additionalProperties: false,
        required: ["order_id", "notification"],
        properties: {
          order_id: { type: "string", format: "uuid", example: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" },
          notification: { $ref: "#/components/schemas/QuoteApprovalNotification" },
        },
      },
      PaymentLink: {
        type: "object",
        additionalProperties: false,
        required: [
          "id",
          "code",
          "slug",
          "status",
          "type",
          "title",
          "description",
          "amount",
          "currency",
          "image_url",
          "interval_count",
          "interval_unit",
          "allow_credit_card",
          "allow_pix",
          "allow_boleto",
          "checkout_config",
          "share_config",
          "metadata",
          "last_paid_at",
          "last_opened_at",
          "expires_at",
          "created_at",
          "updated_at",
          "public_url",
          "active_subscription_count",
          "pending_subscription_count",
          "subscriptions_total",
        ],
        properties: {
          id: { type: "string", format: "uuid", example: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" },
          code: { type: "string", example: "LP-AB12CD" },
          slug: { type: "string", example: "minha-loja" },
          status: { type: "string", example: "active" },
          type: { type: "string", example: "one_time" },
          title: { type: "string", example: "Caneca Premium" },
          description: { type: "string", example: "Pagamento para 10 canecas premium." },
          amount: { type: "number", example: 199.9 },
          currency: { type: "string", example: "BRL" },
          image_url: { type: "string", example: "https://cdn.ktalogu.com/produtos/caneca-capa.png" },
          interval_count: { type: "integer", nullable: true, example: null },
          interval_unit: { type: "string", nullable: true, example: null },
          allow_credit_card: { type: "boolean", example: true },
          allow_pix: { type: "boolean", example: true },
          allow_boleto: { type: "boolean", example: false },
          checkout_config: {
            type: "object",
            example: {
              installments: 3,
            },
          },
          share_config: {
            type: "object",
            example: {
              show_price: true,
            },
          },
          metadata: {
            type: "object",
            example: {
              campaign: "extensao-chrome",
            },
          },
          last_paid_at: { type: "string", nullable: true, format: "date-time", example: null },
          last_opened_at: { type: "string", nullable: true, format: "date-time", example: "2026-06-20T21:00:00.000Z" },
          expires_at: { type: "string", nullable: true, format: "date-time", example: "2026-07-10T12:00:00.000Z" },
          created_at: { type: "string", format: "date-time", example: "2026-06-20T20:00:00.000Z" },
          updated_at: { type: "string", format: "date-time", example: "2026-06-20T20:10:00.000Z" },
          public_url: { type: "string", example: "http://localhost:3001/lp/LP-AB12CD" },
          active_subscription_count: { type: "integer", example: 0 },
          pending_subscription_count: { type: "integer", example: 0 },
          subscriptions_total: { type: "integer", example: 0 },
        },
      },
      PaymentLinkListData: {
        type: "object",
        additionalProperties: false,
        required: ["items"],
        properties: {
          items: {
            type: "array",
            items: { $ref: "#/components/schemas/PaymentLink" },
          },
        },
      },
      PaymentLinkWriteRequest: {
        type: "object",
        additionalProperties: false,
        required: ["title", "amount"],
        properties: {
          title: { type: "string", example: "Caneca Premium" },
          description: { type: "string", example: "Pagamento para 10 canecas premium." },
          status: { type: "string", enum: ["draft", "active", "paused", "archived"], example: "active" },
          type: { type: "string", enum: ["one_time", "subscription"], example: "one_time" },
          amount: { type: "number", example: 199.9 },
          currency: { type: "string", example: "BRL" },
          image_url: { type: "string", example: "https://cdn.ktalogu.com/produtos/caneca-capa.png" },
          interval_count: { type: "integer", nullable: true, example: null },
          interval_unit: { type: "string", nullable: true, enum: ["days", "months", "years"], example: null },
          allow_credit_card: { type: "boolean", example: true },
          allow_pix: { type: "boolean", example: true },
          allow_boleto: { type: "boolean", example: false },
          checkout_config: {
            type: "object",
            example: {
              installments: 3,
            },
          },
          share_config: {
            type: "object",
            example: {
              show_price: true,
            },
          },
          metadata: {
            type: "object",
            example: {
              campaign: "extensao-chrome",
            },
          },
          expires_at: { type: "string", nullable: true, format: "date-time", example: "2026-07-10T12:00:00.000Z" },
        },
      },
      LogoutData: {
        type: "object",
        additionalProperties: false,
        required: ["logged_out"],
        properties: {
          logged_out: { type: "boolean", example: true },
        },
      },
    },
  },
  paths: {
    "/api/v1/health": {
      get: {
        operationId: "getHealth",
        summary: "Health check da API",
        description: "Confirma que a camada `/api/v1` esta operacional e devolve timestamp atual do servico.",
        responses: {
          "200": successResponse(
            "API operacional.",
            { $ref: "#/components/schemas/HealthData" },
            {
              version: "v1",
              service: "ktalogu-api",
              timestamp: "2026-06-21T18:32:10.111Z",
            }
          ),
        },
      },
    },
    "/api/v1/openapi": {
      get: {
        operationId: "getOpenApiDocument",
        summary: "Documento OpenAPI bruto",
        description:
          "Retorna o documento OpenAPI 3.1 puro, sem envelope de resposta, para compatibilidade com Swagger UI, geradores de cliente e validadores externos.",
        responses: {
          "200": {
            description: "Documento OpenAPI 3.1 da API Ktalogu.",
            content: jsonContent(
              {
                type: "object",
                description: "Documento OpenAPI completo.",
                additionalProperties: true,
              },
              {
                openapi: "3.1.0",
                info: {
                  title: "Ktalogu API",
                  version: "1.0.0",
                },
              }
            ),
          },
        },
      },
    },
    "/api/v1/docs": {
      get: {
        operationId: "getDocsUi",
        summary: "Interface Swagger UI",
        description: "Renderiza a documentacao HTML interativa consumindo o documento de `/api/v1/openapi`.",
        responses: {
          "200": {
            description: "HTML da documentacao Swagger UI.",
            content: {
              "text/html": {
                schema: {
                  type: "string",
                  example: "<!doctype html><html lang=\"pt-BR\">...</html>",
                },
              },
            },
          },
        },
      },
    },
    "/api/v1/auth/login": {
      post: {
        operationId: "login",
        summary: "Autentica usuario externo",
        description:
          "Autentica com email e senha usando Supabase Auth e retorna access token, refresh token, expiracao e contexto atual da empresa.",
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/LoginRequest" },
            {
              email: "owner@empresa.com",
              password: "minha-senha-segura",
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Sessao criada com sucesso.",
            {
              type: "object",
              additionalProperties: false,
              required: ["session"],
              properties: {
                session: { $ref: "#/components/schemas/SessionPayload" },
              },
            },
            {
              session: {
                access_token: "eyJhbGciOi...",
                refresh_token: "refresh-token-exemplo",
                token_type: "bearer",
                expires_at: 1763630112,
                user: {
                  id: "8a33f8f4-6b8d-4ab3-9a90-2b4f5f34a999",
                  email: "owner@empresa.com",
                },
                company: {
                  id: "11111111-1111-4111-8111-111111111111",
                  owner_id: "22222222-2222-4222-8222-222222222222",
                  tenant_ids: [
                    "11111111-1111-4111-8111-111111111111",
                    "22222222-2222-4222-8222-222222222222",
                  ],
                  permissions: ["products.read", "quotes.write", "financial.read"],
                },
              },
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou campos obrigatorios ausentes.",
            400,
            "missing_email",
            "Informe o email."
          ),
          "401": errorResponse(
            "Credenciais invalidas.",
            401,
            "invalid_credentials",
            "Credenciais invalidas."
          ),
          "429": errorResponse(
            "Rate limit excedido para autenticacao.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 10,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/auth/refresh": {
      post: {
        operationId: "refreshSession",
        summary: "Renova a sessao",
        description: "Recebe um refresh token valido e devolve nova sessao com access token atualizado.",
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/RefreshRequest" },
            {
              refresh_token: "refresh-token-exemplo",
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Sessao renovada com sucesso.",
            {
              type: "object",
              additionalProperties: false,
              required: ["session"],
              properties: {
                session: { $ref: "#/components/schemas/SessionPayload" },
              },
            },
            {
              session: {
                access_token: "eyJhbGciOi...novo",
                refresh_token: "refresh-token-exemplo-novo",
                token_type: "bearer",
                expires_at: 1763631112,
                user: {
                  id: "8a33f8f4-6b8d-4ab3-9a90-2b4f5f34a999",
                  email: "owner@empresa.com",
                },
                company: {
                  id: "11111111-1111-4111-8111-111111111111",
                  owner_id: "22222222-2222-4222-8222-222222222222",
                  tenant_ids: [
                    "11111111-1111-4111-8111-111111111111",
                    "22222222-2222-4222-8222-222222222222",
                  ],
                  permissions: ["products.read", "quotes.write", "financial.read"],
                },
              },
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou campo obrigatorio ausente.",
            400,
            "missing_refresh_token",
            "Refresh token obrigatorio."
          ),
          "401": errorResponse(
            "Refresh token invalido ou expirado.",
            401,
            "invalid_refresh_token",
            "Refresh token invalido."
          ),
          "429": errorResponse(
            "Rate limit excedido na renovacao de sessao.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 20,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/auth/logout": {
      post: {
        operationId: "logout",
        summary: "Encerra a sessao",
        description:
          "Recebe access token via `Authorization: Bearer` e `refresh_token` no corpo para invalidar a sessao atual no provedor de autenticacao.",
        security: [{ bearerAuth: [] }],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/LogoutRequest" },
            {
              refresh_token: "refresh-token-exemplo",
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Sessao encerrada com sucesso.",
            { $ref: "#/components/schemas/LogoutData" },
            { logged_out: true },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou campo obrigatorio ausente.",
            400,
            "missing_refresh_token",
            "Refresh token obrigatorio para logout."
          ),
          "401": errorResponse(
            "Token Bearer ausente ou invalido.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "429": errorResponse(
            "Rate limit excedido no logout.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 30,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/auth/me": {
      get: {
        operationId: "getAuthenticatedContext",
        summary: "Retorna o contexto autenticado",
        description:
          "Valida o token JWT, verifica expiracao, resolve a empresa atual e devolve usuario autenticado mais permissoes efetivas.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        responses: {
          "200": successResponse(
            "Contexto autenticado retornado com sucesso.",
            { $ref: "#/components/schemas/AuthMeData" },
            {
              user: {
                id: "8a33f8f4-6b8d-4ab3-9a90-2b4f5f34a999",
                email: "owner@empresa.com",
              },
              company: {
                id: "11111111-1111-4111-8111-111111111111",
                owner_id: "22222222-2222-4222-8222-222222222222",
                tenant_ids: [
                  "11111111-1111-4111-8111-111111111111",
                  "22222222-2222-4222-8222-222222222222",
                ],
                permissions: ["products.read", "categories.write", "quotes.write", "financial.read"],
              },
            },
            true
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "token_expired",
            "Token expirado."
          ),
          "403": errorResponse(
            "Tentativa de acesso cruzado entre empresas.",
            403,
            "cross_company_access_denied",
            "O token autenticado nao possui acesso a empresa solicitada."
          ),
          "429": errorResponse(
            "Rate limit excedido na consulta do contexto autenticado.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/extension/customer-context": {
      get: {
        operationId: "getExtensionCustomerContext",
        summary: "Contexto agregado do cliente para extensao",
        description:
          "Recebe o telefone da conversa e monta, em uma unica resposta, o contexto comercial do cliente para a extensao Chrome. A agregacao acontece no servidor da Ktalogu, sem exigir multiplas consultas da extensao.",
        security: [{ bearerAuth: [] }],
        parameters: [
          companyScopeHeaderParameter,
          {
            name: "phone",
            in: "query",
            required: true,
            description:
              "Telefone da conversa em formato numerico. A API normaliza o valor para busca por `phone` e `whatsapp` do cliente.",
            schema: {
              type: "string",
              example: "5511999999999",
            },
          },
        ],
        responses: {
          "200": successResponse(
            "Contexto agregado retornado com sucesso.",
            { $ref: "#/components/schemas/ExtensionCustomerContextData" },
            {
              phone: "5511999999999",
              customer_found: true,
              customer: {
                id: "99999999-9999-4999-8999-999999999999",
                name: "Maria Silva",
                company_name: "Loja Exemplo",
                type: "pj",
                email: "maria@empresa.com",
                phone: "+55 11 4002-8922",
                whatsapp: "+55 11 99999-9999",
                notes: "Cliente recorrente de brindes corporativos.",
                tags: ["vip", "revenda"],
                active: true,
                created_at: "2026-05-10T12:00:00.000Z",
                updated_at: "2026-06-21T18:00:00.000Z",
              },
              company: {
                id: "11111111-1111-4111-8111-111111111111",
                profile_id: "22222222-2222-4222-8222-222222222222",
                name: "Loja Exemplo",
                owner_id: "22222222-2222-4222-8222-222222222222",
                store_name: "Loja Exemplo",
                logo_url: "https://cdn.ktalogu.com/logo.png",
                cnpj: "12.345.678/0001-99",
                phone: "+55 11 4002-8922",
                company_whatsapp: "+55 11 99999-0000",
                address_zip: "01310-100",
                address_street: "Avenida Paulista",
                address_number: "1000",
                address_complement: "10 andar",
                address_neighborhood: "Bela Vista",
                address_city: "Sao Paulo",
                address_state: "SP",
                address: "Avenida Paulista, 1000 - Bela Vista - Sao Paulo/SP",
              },
              recent_quotes: [
                {
                  id: "66666666-6666-4666-8666-666666666666",
                  number: 123,
                  status: "sent",
                  total: 1490.9,
                  created_at: "2026-06-21T08:10:00.000Z",
                  updated_at: "2026-06-21T08:10:00.000Z",
                  client_name: "Loja Exemplo",
                },
              ],
              recent_orders: [
                {
                  id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                  number: 456,
                  status: "finished",
                  total_amount: 1890.5,
                  financial_status: "paid",
                  created_at: "2026-06-20T10:00:00.000Z",
                  updated_at: "2026-06-20T12:00:00.000Z",
                  quote_id: "66666666-6666-4666-8666-666666666666",
                  quote_number: 123,
                  quote_title: "Orcamento de brindes corporativos",
                },
              ],
              top_products: [
                {
                  product_id: "55555555-5555-4555-8555-555555555555",
                  product_name: "Caneca Branca 325ml",
                  quantity: 120,
                  total_amount: 4788,
                  sources: ["order", "quote"],
                  product: {
                    id: "55555555-5555-4555-8555-555555555555",
                    name: "Caneca Branca 325ml",
                    description: "Caneca de ceramica pronta para sublimacao.",
                    price: 39.9,
                    category_id: "33333333-3333-4333-8333-333333333333",
                    category: {
                      id: "33333333-3333-4333-8333-333333333333",
                      name: "Canecas",
                      slug: "canecas",
                    },
                    active: true,
                    image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
                    images: [],
                    mockups: [],
                    files: [],
                  },
                },
              ],
              commercial_stats: {
                orders_count: 12,
                quotes_count: 18,
                total_purchased: 8450.9,
                average_ticket: 704.24,
                last_purchase_at: "2026-06-20T10:00:00.000Z",
                last_quote_at: "2026-06-21T08:10:00.000Z",
                last_interaction_at: "2026-06-21T08:10:00.000Z",
                current_status: {
                  code: "customer",
                  label: "Cliente com compras",
                },
              },
            },
            true
          ),
          "400": errorResponse(
            "Telefone ausente ou invalido.",
            400,
            "invalid_phone",
            "Informe um telefone valido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Sem permissao para leitura do contexto comercial.",
            403,
            "forbidden",
            "Sem permissao para visualizar clientes."
          ),
          "429": errorResponse(
            "Rate limit excedido para a extensao.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/extension/conversation-context": {
      get: {
        operationId: "getExtensionConversationContext",
        summary: "Contexto agregado da conversa para extensao",
        description:
          "Prepara o contrato evolutivo da extensao Chrome para uma conversa aberta no WhatsApp Web, reunindo cliente, historico comercial, produtos relacionados e sugestoes disponiveis com dados ja existentes.",
        security: [{ bearerAuth: [] }],
        parameters: [
          companyScopeHeaderParameter,
          {
            name: "phone",
            in: "query",
            required: true,
            description: "Telefone da conversa em formato numerico.",
            schema: {
              type: "string",
              example: "5511999999999",
            },
          },
        ],
        responses: {
          "200": successResponse(
            "Contexto da conversa retornado com sucesso.",
            { $ref: "#/components/schemas/ExtensionConversationContextData" },
            {
              phone: "5511999999999",
              customer_found: true,
              customer: {
                id: "99999999-9999-4999-8999-999999999999",
                name: "Maria Silva",
                company_name: "Loja Exemplo",
                type: "pj",
                email: "maria@empresa.com",
                phone: "+55 11 4002-8922",
                whatsapp: "+55 11 99999-9999",
                notes: "Cliente recorrente de brindes corporativos.",
                tags: ["vip", "revenda"],
                active: true,
                created_at: "2026-05-10T12:00:00.000Z",
                updated_at: "2026-06-21T18:00:00.000Z",
              },
              recent_quotes: [
                {
                  id: "66666666-6666-4666-8666-666666666666",
                  number: 123,
                  status: "sent",
                  total: 1490.9,
                  created_at: "2026-06-21T08:10:00.000Z",
                  updated_at: "2026-06-21T08:10:00.000Z",
                  client_name: "Loja Exemplo",
                },
              ],
              recent_orders: [
                {
                  id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                  number: 456,
                  status: "finished",
                  total_amount: 1890.5,
                  financial_status: "paid",
                  created_at: "2026-06-20T10:00:00.000Z",
                  updated_at: "2026-06-20T12:00:00.000Z",
                  quote_id: "66666666-6666-4666-8666-666666666666",
                  quote_number: 123,
                  quote_title: "Orcamento de brindes corporativos",
                },
              ],
              related_products: [
                {
                  product_id: "55555555-5555-4555-8555-555555555555",
                  product_name: "Caneca Branca 325ml",
                  interactions: {
                    quantity: 120,
                    total_amount: 4788,
                    sources: ["order", "quote"],
                  },
                  product: {
                    id: "55555555-5555-4555-8555-555555555555",
                    name: "Caneca Branca 325ml",
                    description: "Caneca de ceramica pronta para sublimacao.",
                    price: 39.9,
                    category_id: "33333333-3333-4333-8333-333333333333",
                    category: {
                      id: "33333333-3333-4333-8333-333333333333",
                      name: "Canecas",
                      slug: "canecas",
                    },
                    active: true,
                    image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
                    images: [],
                    mockups: [],
                    files: [],
                  },
                },
              ],
              commercial_history: {
                total_orders: 12,
                total_quotes: 18,
                total_purchased: 8450.9,
                average_ticket: 704.24,
                latest_interaction_at: "2026-06-21T08:10:00.000Z",
                top_products: [
                  {
                    product_id: "55555555-5555-4555-8555-555555555555",
                    product_name: "Caneca Branca 325ml",
                    quantity: 120,
                    total_amount: 4788,
                    sources: ["order", "quote"],
                    product: null,
                  },
                ],
              },
              suggestions_available: {
                can_view_customer: true,
                can_review_recent_quotes: true,
                can_review_recent_orders: true,
                can_suggest_products: true,
                can_prepare_quote: true,
              },
            },
            true
          ),
          "400": errorResponse(
            "Telefone ausente ou invalido.",
            400,
            "invalid_phone",
            "Informe um telefone valido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Sem permissao para leitura do contexto comercial.",
            403,
            "forbidden",
            "Sem permissao para visualizar clientes."
          ),
          "429": errorResponse(
            "Rate limit excedido para a extensao.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/company": {
      get: {
        operationId: "getCompany",
        summary: "Consulta perfil da empresa",
        description: "Retorna os dados consolidados de empresa e perfil usados pelo tenant autenticado.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        responses: {
          "200": successResponse(
            "Perfil da empresa retornado com sucesso.",
            { $ref: "#/components/schemas/CompanyProfile" },
            {
              id: "11111111-1111-4111-8111-111111111111",
              profile_id: "22222222-2222-4222-8222-222222222222",
              name: "Loja Exemplo",
              owner_id: "22222222-2222-4222-8222-222222222222",
              store_name: "Loja Exemplo",
              logo_url: "https://cdn.ktalogu.com/logo.png",
              cnpj: "12.345.678/0001-99",
              phone: "+55 11 4002-8922",
              company_whatsapp: "+55 11 99999-0000",
              address_zip: "01310-100",
              address_street: "Avenida Paulista",
              address_number: "1000",
              address_complement: "10 andar",
              address_neighborhood: "Bela Vista",
              address_city: "Sao Paulo",
              address_state: "SP",
              address: "Avenida Paulista, 1000 - Bela Vista - Sao Paulo/SP",
            },
            true
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Acesso negado por empresa ou permissao.",
            403,
            "cross_company_access_denied",
            "O token autenticado nao possui acesso a empresa solicitada."
          ),
          "429": errorResponse(
            "Rate limit excedido na consulta de empresa.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      put: {
        operationId: "updateCompany",
        summary: "Atualiza perfil da empresa",
        description:
          "Atualiza somente os campos de perfil permitidos para a empresa autenticada. Requer permissao `company.data.write`.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/CompanyUpdateRequest" },
            {
              store_name: "Loja Exemplo",
              phone: "+55 11 4002-8922",
              company_whatsapp: "+55 11 99999-0000",
              address_city: "Sao Paulo",
              address_state: "SP",
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Perfil da empresa atualizado com sucesso.",
            { $ref: "#/components/schemas/CompanyProfile" },
            {
              id: "11111111-1111-4111-8111-111111111111",
              profile_id: "22222222-2222-4222-8222-222222222222",
              name: "Loja Exemplo",
              owner_id: "22222222-2222-4222-8222-222222222222",
              store_name: "Loja Exemplo",
              logo_url: "https://cdn.ktalogu.com/logo.png",
              cnpj: "12.345.678/0001-99",
              phone: "+55 11 4002-8922",
              company_whatsapp: "+55 11 99999-0000",
              address_zip: "01310-100",
              address_street: "Avenida Paulista",
              address_number: "1000",
              address_complement: "10 andar",
              address_neighborhood: "Bela Vista",
              address_city: "Sao Paulo",
              address_state: "SP",
              address: "Avenida Paulista, 1000 - Bela Vista - Sao Paulo/SP",
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou falha ao atualizar perfil.",
            400,
            "invalid_json_body",
            "O corpo da requisicao deve ser um objeto JSON."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para editar a empresa.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na atualizacao da empresa.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/products": {
      get: {
        operationId: "listProducts",
        summary: "Lista produtos",
        description:
          "Lista produtos visiveis para a empresa autenticada, com filtros por texto, categoria, status e paginacao.",
        security: [{ bearerAuth: [] }],
        parameters: [
          companyScopeHeaderParameter,
          {
            name: "q",
            in: "query",
            required: false,
            description: "Filtro textual aplicado ao nome do produto.",
            schema: { type: "string", example: "caneca" },
          },
          {
            name: "category",
            in: "query",
            required: false,
            description: "Filtra por categoria do produto.",
            schema: { type: "string", format: "uuid", example: "33333333-3333-4333-8333-333333333333" },
          },
          {
            name: "status",
            in: "query",
            required: false,
            description: "Estado do produto retornado.",
            schema: {
              type: "string",
              enum: ["all", "active", "inactive"],
              default: "all",
            },
          },
          {
            name: "page",
            in: "query",
            required: false,
            description: "Pagina atual, iniciando em 1.",
            schema: { type: "integer", minimum: 1, default: 1, example: 1 },
          },
          {
            name: "per_page",
            in: "query",
            required: false,
            description: "Quantidade de registros por pagina. O backend limita a 100.",
            schema: { type: "integer", minimum: 1, maximum: 100, default: 20, example: 20 },
          },
        ],
        responses: {
          "200": successResponse(
            "Produtos listados com sucesso.",
            { $ref: "#/components/schemas/ProductListData" },
            {
              items: [
                {
                  id: "55555555-5555-4555-8555-555555555555",
                  name: "Caneca Branca 325ml",
                  description: "Caneca de ceramica pronta para sublimacao.",
                  price: 39.9,
                  category_id: "33333333-3333-4333-8333-333333333333",
                  category: {
                    id: "33333333-3333-4333-8333-333333333333",
                    name: "Canecas",
                    slug: "canecas",
                  },
                  active: true,
                  image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
                  images: [
                    {
                      image_url: "https://cdn.ktalogu.com/produtos/caneca-1.png",
                      sort_order: 0,
                    },
                  ],
                  mockups: [],
                  files: [],
                },
              ],
              pagination: {
                page: 1,
                per_page: 20,
                total: 1,
              },
            },
            true
          ),
          "400": errorResponse(
            "Parametro de consulta invalido.",
            400,
            "invalid_status",
            "Status invalido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler produtos.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na listagem de produtos.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/products/{id}": {
      get: {
        operationId: "getProductById",
        summary: "Busca produto por ID",
        description: "Retorna um produto especifico dentro do escopo da empresa autenticada.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID do produto")],
        responses: {
          "200": successResponse(
            "Produto encontrado com sucesso.",
            { $ref: "#/components/schemas/Product" },
            {
              id: "55555555-5555-4555-8555-555555555555",
              name: "Caneca Branca 325ml",
              description: "Caneca de ceramica pronta para sublimacao.",
              price: 39.9,
              category_id: "33333333-3333-4333-8333-333333333333",
              category: {
                id: "33333333-3333-4333-8333-333333333333",
                name: "Canecas",
                slug: "canecas",
              },
              active: true,
              image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
              images: [
                {
                  image_url: "https://cdn.ktalogu.com/produtos/caneca-1.png",
                  sort_order: 0,
                },
              ],
              mockups: [],
              files: [],
            },
            true
          ),
          "400": errorResponse(
            "Identificador de produto invalido.",
            400,
            "invalid_product_id",
            "Produto invalido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler produtos.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Produto nao encontrado.",
            404,
            "product_not_found",
            "Produto nao encontrado."
          ),
          "429": errorResponse(
            "Rate limit excedido na leitura de produto.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/categories": {
      get: {
        operationId: "listCategories",
        summary: "Lista categorias",
        description: "Lista as categorias disponiveis para a empresa autenticada.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        responses: {
          "200": successResponse(
            "Categorias listadas com sucesso.",
            { $ref: "#/components/schemas/CategoryListData" },
            {
              items: [
                {
                  id: "33333333-3333-4333-8333-333333333333",
                  name: "Canecas",
                  slug: "canecas",
                  pricing_rule: {
                    marginTargetPct: 50,
                    marginMinPct: 35,
                    rounding: { type: "END_WITH", cents: 90 },
                  },
                  is_visible: true,
                  parent_id: null,
                },
              ],
            },
            true
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler categorias.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na listagem de categorias.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      post: {
        operationId: "createCategory",
        summary: "Cria categoria",
        description: "Cria uma categoria para a empresa autenticada. Requer permissao `categories.write`.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/CategoryWriteRequest" },
            {
              name: "Canecas Personalizadas",
              slug: "canecas-personalizadas",
              is_visible: true,
              pricing_rule: {
                marginTargetPct: 50,
                marginMinPct: 35,
                rounding: { type: "END_WITH", cents: 90 },
              },
              parent_id: null,
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Categoria criada com sucesso.",
            { $ref: "#/components/schemas/Category" },
            {
              id: "33333333-3333-4333-8333-333333333333",
              name: "Canecas Personalizadas",
              slug: "canecas-personalizadas",
              pricing_rule: {
                marginTargetPct: 50,
                marginMinPct: 35,
                rounding: { type: "END_WITH", cents: 90 },
              },
              is_visible: true,
              parent_id: null,
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou dados de categoria invalidos.",
            400,
            "invalid_name",
            "Nome e obrigatorio."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para criar categorias.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na criacao de categorias.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/categories/{id}": {
      get: {
        operationId: "getCategoryById",
        summary: "Busca categoria por ID",
        description: "Retorna uma categoria especifica dentro do escopo da empresa autenticada.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID da categoria")],
        responses: {
          "200": successResponse(
            "Categoria encontrada com sucesso.",
            { $ref: "#/components/schemas/Category" },
            {
              id: "33333333-3333-4333-8333-333333333333",
              name: "Canecas",
              slug: "canecas",
              pricing_rule: {
                marginTargetPct: 50,
                marginMinPct: 35,
                rounding: { type: "END_WITH", cents: 90 },
              },
              is_visible: true,
              parent_id: null,
            },
            true
          ),
          "400": errorResponse(
            "Identificador de categoria invalido.",
            400,
            "invalid_category_id",
            "Categoria invalida."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler categorias.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Categoria nao encontrada.",
            404,
            "category_not_found",
            "Categoria nao encontrada."
          ),
          "429": errorResponse(
            "Rate limit excedido na leitura de categoria.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      patch: {
        operationId: "updateCategory",
        summary: "Atualiza categoria",
        description: "Atualiza campos permitidos da categoria. Requer permissao `categories.write`.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID da categoria")],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/CategoryWriteRequest" },
            {
              name: "Canecas Linha Premium",
              is_visible: true,
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Categoria atualizada com sucesso.",
            { $ref: "#/components/schemas/UpdateAck" },
            { updated: true },
            true
          ),
          "400": errorResponse(
            "Identificador invalido, patch vazio ou dados inconsistentes.",
            400,
            "empty_patch",
            "Nada para atualizar."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para atualizar categorias.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Categoria nao encontrada.",
            404,
            "category_not_found",
            "Categoria nao encontrada."
          ),
          "429": errorResponse(
            "Rate limit excedido na atualizacao de categoria.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      delete: {
        operationId: "deleteCategory",
        summary: "Remove categoria",
        description: "Exclui uma categoria pertencente ao escopo da empresa autenticada.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID da categoria")],
        responses: {
          "200": successResponse(
            "Categoria removida com sucesso.",
            { $ref: "#/components/schemas/DeleteAck" },
            { deleted: true },
            true
          ),
          "400": errorResponse(
            "Identificador de categoria invalido.",
            400,
            "invalid_category_id",
            "Categoria invalida."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para excluir categorias.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Categoria nao encontrada.",
            404,
            "category_not_found",
            "Categoria nao encontrada."
          ),
          "429": errorResponse(
            "Rate limit excedido na exclusao de categoria.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 30,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/quotes": {
      get: {
        operationId: "listQuotes",
        summary: "Lista orcamentos",
        description: "Lista os orcamentos da empresa autenticada, com filtro textual opcional.",
        security: [{ bearerAuth: [] }],
        parameters: [
          companyScopeHeaderParameter,
          {
            name: "q",
            in: "query",
            required: false,
            description: "Filtro textual aplicado em titulo e observacoes internas do orcamento.",
            schema: { type: "string", example: "brindes" },
          },
        ],
        responses: {
          "200": successResponse(
            "Orcamentos listados com sucesso.",
            { $ref: "#/components/schemas/QuoteListData" },
            {
              items: [
                {
                  id: "66666666-6666-4666-8666-666666666666",
                  number: 123,
                  status: "draft",
                  total: 149.9,
                  created_at: "2026-06-21T17:30:00.000Z",
                  updated_at: "2026-06-21T17:30:00.000Z",
                  client_name: "Empresa XPTO",
                },
              ],
            },
            true
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler orcamentos.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na listagem de orcamentos.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      post: {
        operationId: "createQuote",
        summary: "Cria orcamento",
        description:
          "Cria um novo orcamento para um cliente da empresa autenticada, validando itens, vendedores e limites de quantidade configurados nos produtos.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/QuoteCreateRequest" },
            {
              client_id: "99999999-9999-4999-8999-999999999999",
              title: "Orcamento de brindes corporativos",
              notes: "Entrega em 5 dias uteis.",
              seller_mode: "single",
              primary_seller_user_id: "88888888-8888-4888-8888-888888888888",
              items: [
                {
                  product_id: "55555555-5555-4555-8555-555555555555",
                  unit_type: "unit",
                  title: "Caneca Branca 325ml",
                  description: "Arte incluida",
                  quantity: 10,
                  unit_price: 14.99,
                  unit_cost: 8.25,
                },
              ],
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Orcamento criado com sucesso.",
            { $ref: "#/components/schemas/QuoteCreateData" },
            {
              quote_id: "66666666-6666-4666-8666-666666666666",
              quote_number: 123,
              total: 149.9,
              expires_at: "2026-06-30T23:59:59.000Z",
              share_url: "http://localhost:3001/minha-loja/o/3f7d8f8fd0a0c0b0ab12cd34ef56ab78",
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou payload inconsistente para criacao do orcamento.",
            400,
            "missing_items",
            "Adicione ao menos 1 item no orcamento."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para criar orcamentos.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Cliente informado nao encontrado.",
            404,
            "client_not_found",
            "Cliente nao encontrado."
          ),
          "429": errorResponse(
            "Rate limit excedido na criacao de orcamentos.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/quotes/{id}/approve": {
      post: {
        operationId: "approveQuote",
        summary: "Aprova orcamento e gera pedido",
        description:
          "Aprova o orcamento informado, executa a RPC de geracao de pedido e devolve identificador do pedido gerado.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID do orcamento")],
        responses: {
          "200": successResponse(
            "Orcamento aprovado e pedido gerado com sucesso.",
            { $ref: "#/components/schemas/QuoteApprovalData" },
            {
              order_id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
              notification: {
                clientName: "Empresa XPTO",
                whatsapp: "+55 11 99999-0000",
                whatsappNotify: true,
                orderNumber: 456,
                quoteNumber: 123,
                status: "approved",
              },
            },
            true
          ),
          "400": errorResponse(
            "Identificador invalido ou falha ao aprovar o orcamento.",
            400,
            "invalid_quote_id",
            "Orcamento invalido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para gerar pedidos.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na aprovacao do orcamento.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 30,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/payment-links": {
      get: {
        operationId: "listPaymentLinks",
        summary: "Lista links de pagamento",
        description: "Lista links de pagamento visiveis para a empresa autenticada.",
        security: [{ bearerAuth: [] }],
        parameters: [
          companyScopeHeaderParameter,
          {
            name: "lookup",
            in: "query",
            required: false,
            description: "Campo reservado para lookup textual futuro sem quebra de contrato.",
            schema: { type: "string", example: "LP-AB12CD" },
          },
          {
            name: "q",
            in: "query",
            required: false,
            description: "Campo reservado para filtro textual futuro sem quebra de contrato.",
            schema: { type: "string", example: "caneca" },
          },
        ],
        responses: {
          "200": successResponse(
            "Links de pagamento listados com sucesso.",
            { $ref: "#/components/schemas/PaymentLinkListData" },
            {
              items: [
                {
                  id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
                  code: "LP-AB12CD",
                  slug: "minha-loja",
                  status: "active",
                  type: "one_time",
                  title: "Caneca Premium",
                  description: "Pagamento para 10 canecas premium.",
                  amount: 199.9,
                  currency: "BRL",
                  image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
                  interval_count: null,
                  interval_unit: null,
                  allow_credit_card: true,
                  allow_pix: true,
                  allow_boleto: false,
                  checkout_config: { installments: 3 },
                  share_config: { show_price: true },
                  metadata: { campaign: "extensao-chrome" },
                  last_paid_at: null,
                  last_opened_at: "2026-06-20T21:00:00.000Z",
                  expires_at: "2026-07-10T12:00:00.000Z",
                  created_at: "2026-06-20T20:00:00.000Z",
                  updated_at: "2026-06-20T20:10:00.000Z",
                  public_url: "http://localhost:3001/lp/LP-AB12CD",
                  active_subscription_count: 0,
                  pending_subscription_count: 0,
                  subscriptions_total: 0,
                },
              ],
            },
            true
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler links de pagamento.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na listagem de links de pagamento.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      post: {
        operationId: "createPaymentLink",
        summary: "Cria link de pagamento",
        description: "Cria um link de pagamento para a empresa autenticada. Requer permissao `financial.write`.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/PaymentLinkWriteRequest" },
            {
              title: "Caneca Premium",
              description: "Pagamento para 10 canecas premium.",
              status: "active",
              type: "one_time",
              amount: 199.9,
              currency: "BRL",
              allow_credit_card: true,
              allow_pix: true,
              allow_boleto: false,
              checkout_config: { installments: 3 },
              share_config: { show_price: true },
              metadata: { campaign: "extensao-chrome" },
              expires_at: "2026-07-10T12:00:00.000Z",
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Link de pagamento criado com sucesso.",
            { $ref: "#/components/schemas/PaymentLink" },
            {
              id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
              code: "LP-AB12CD",
              slug: "minha-loja",
              status: "active",
              type: "one_time",
              title: "Caneca Premium",
              description: "Pagamento para 10 canecas premium.",
              amount: 199.9,
              currency: "BRL",
              image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
              interval_count: null,
              interval_unit: null,
              allow_credit_card: true,
              allow_pix: true,
              allow_boleto: false,
              checkout_config: { installments: 3 },
              share_config: { show_price: true },
              metadata: { campaign: "extensao-chrome" },
              last_paid_at: null,
              last_opened_at: null,
              expires_at: "2026-07-10T12:00:00.000Z",
              created_at: "2026-06-20T20:00:00.000Z",
              updated_at: "2026-06-20T20:00:00.000Z",
              public_url: "http://localhost:3001/lp/LP-AB12CD",
              active_subscription_count: 0,
              pending_subscription_count: 0,
              subscriptions_total: 0,
            },
            true
          ),
          "400": errorResponse(
            "JSON invalido ou payload inconsistente para criacao do link.",
            400,
            "invalid_amount",
            "Informe um valor maior que zero."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para criar links de pagamento.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na criacao de links de pagamento.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
    "/api/v1/payment-links/{id}": {
      get: {
        operationId: "getPaymentLinkById",
        summary: "Busca link de pagamento por ID",
        description: "Retorna um link de pagamento especifico do escopo autenticado.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID do link de pagamento")],
        responses: {
          "200": successResponse(
            "Link de pagamento encontrado com sucesso.",
            { $ref: "#/components/schemas/PaymentLink" },
            {
              id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
              code: "LP-AB12CD",
              slug: "minha-loja",
              status: "active",
              type: "one_time",
              title: "Caneca Premium",
              description: "Pagamento para 10 canecas premium.",
              amount: 199.9,
              currency: "BRL",
              image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
              interval_count: null,
              interval_unit: null,
              allow_credit_card: true,
              allow_pix: true,
              allow_boleto: false,
              checkout_config: { installments: 3 },
              share_config: { show_price: true },
              metadata: { campaign: "extensao-chrome" },
              last_paid_at: null,
              last_opened_at: "2026-06-20T21:00:00.000Z",
              expires_at: "2026-07-10T12:00:00.000Z",
              created_at: "2026-06-20T20:00:00.000Z",
              updated_at: "2026-06-20T20:10:00.000Z",
              public_url: "http://localhost:3001/lp/LP-AB12CD",
              active_subscription_count: 0,
              pending_subscription_count: 0,
              subscriptions_total: 0,
            },
            true
          ),
          "400": errorResponse(
            "Identificador de link de pagamento invalido.",
            400,
            "invalid_payment_link_id",
            "Link de pagamento invalido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para ler links de pagamento.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "404": errorResponse(
            "Link de pagamento nao encontrado.",
            404,
            "payment_link_not_found",
            "Link de pagamento nao encontrado."
          ),
          "429": errorResponse(
            "Rate limit excedido na leitura do link.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 120,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      patch: {
        operationId: "updatePaymentLink",
        summary: "Atualiza link de pagamento",
        description: "Atualiza um link de pagamento existente. Requer permissao `financial.write`.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID do link de pagamento")],
        requestBody: {
          required: true,
          content: jsonContent(
            { $ref: "#/components/schemas/PaymentLinkWriteRequest" },
            {
              title: "Caneca Premium",
              status: "paused",
              amount: 199.9,
              allow_credit_card: true,
              allow_pix: true,
            }
          ),
        },
        responses: {
          "200": successResponse(
            "Link de pagamento atualizado com sucesso.",
            { $ref: "#/components/schemas/PaymentLink" },
            {
              id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
              code: "LP-AB12CD",
              slug: "minha-loja",
              status: "paused",
              type: "one_time",
              title: "Caneca Premium",
              description: "Pagamento para 10 canecas premium.",
              amount: 199.9,
              currency: "BRL",
              image_url: "https://cdn.ktalogu.com/produtos/caneca-capa.png",
              interval_count: null,
              interval_unit: null,
              allow_credit_card: true,
              allow_pix: true,
              allow_boleto: false,
              checkout_config: { installments: 3 },
              share_config: { show_price: true },
              metadata: { campaign: "extensao-chrome" },
              last_paid_at: null,
              last_opened_at: "2026-06-20T21:00:00.000Z",
              expires_at: "2026-07-10T12:00:00.000Z",
              created_at: "2026-06-20T20:00:00.000Z",
              updated_at: "2026-06-20T20:12:00.000Z",
              public_url: "http://localhost:3001/lp/LP-AB12CD",
              active_subscription_count: 0,
              pending_subscription_count: 0,
              subscriptions_total: 0,
            },
            true
          ),
          "400": errorResponse(
            "Identificador invalido ou payload inconsistente para atualizacao.",
            400,
            "invalid_amount",
            "Informe um valor maior que zero."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para atualizar links de pagamento.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na atualizacao do link.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 60,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
      delete: {
        operationId: "deletePaymentLink",
        summary: "Exclui link de pagamento",
        description: "Exclui um link de pagamento do escopo autenticado.",
        security: [{ bearerAuth: [] }],
        parameters: [companyScopeHeaderParameter, idPathParameter("id", "ID do link de pagamento")],
        responses: {
          "200": successResponse(
            "Link de pagamento removido com sucesso.",
            { $ref: "#/components/schemas/DeleteAck" },
            { deleted: true },
            true
          ),
          "400": errorResponse(
            "Identificador de link de pagamento invalido.",
            400,
            "invalid_payment_link_id",
            "Link de pagamento invalido."
          ),
          "401": errorResponse(
            "Token ausente, invalido ou expirado.",
            401,
            "missing_bearer_token",
            "Token Bearer obrigatorio."
          ),
          "403": errorResponse(
            "Usuario sem permissao para excluir links de pagamento.",
            403,
            "forbidden",
            "Sem permissao para acessar este recurso."
          ),
          "429": errorResponse(
            "Rate limit excedido na exclusao do link.",
            429,
            "rate_limited",
            "Limite de requisicoes excedido.",
            {
              limit: 30,
              reset_at: 1763628292000,
            },
            true
          ),
        },
      },
    },
  },
} as const;
