{
  "openapi": "3.1.0",
  "info": {
    "title": "Ablakunio Public API",
    "version": "0.1.0",
    "description": "Publikus, gép-olvasható felület az Ablakunio (SM-UNIO Nyílászáró Kft., Tiszafüred) szolgáltatásaihoz: egyedi méretű nyílászárók árbecslése, raktárkészlet, ajánlatkérés. Egyben az AI-ágensek MCP-szervere is elérhető a /api/mcp végponton (JSON-RPC, Streamable HTTP).",
    "contact": {
      "name": "Ablakunio",
      "url": "https://www.ablakunio.com",
      "email": "info@ablakunio.com"
    }
  },
  "servers": [
    { "url": "https://www.ablakunio.com", "description": "Production" }
  ],
  "tags": [
    { "name": "pricing", "description": "Egyedi méretű árbecslés" },
    { "name": "inventory", "description": "Raktárkészlet" },
    { "name": "lead", "description": "Ajánlatkérés / visszahívás" },
    { "name": "mcp", "description": "Model Context Protocol végpont AI-ágenseknek" }
  ],
  "paths": {
    "/api/quote/custom-calculate": {
      "post": {
        "tags": ["pricing"],
        "operationId": "getCustomPriceEstimate",
        "summary": "Egyedi méretű nyílászáró tájékoztató bruttó ára",
        "description": "Élő, egyedi méretre számolt tájékoztató (ÁFA-s) ár. Nincs fix SKU — a méret és paraméterek alapján számol. A végleges ár helyszíni felmérés után pontos.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PriceEstimateRequest" },
              "example": { "width": 1200, "height": 1500, "unit": "mm", "type": "window", "glazing": "triple", "color": "Fehér" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ár kiszámítva",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceEstimateResponse" } } }
          },
          "400": { "description": "Hiányzó/érvénytelen méret", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit" }
        }
      }
    },
    "/api/quote/check-stock": {
      "post": {
        "tags": ["inventory"],
        "operationId": "checkStock",
        "summary": "Raktáron lévő szabvány nyílászárók a megadott mérethez",
        "description": "Megnézi, van-e a megadott mérethez közeli, raktáron lévő szabvány termék (gyorsabb, olcsóbb opció az egyedi gyártás helyett).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/StockCheckRequest" },
              "example": { "width": 1200, "height": 1500, "unit": "mm", "type": "window" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Találatok (üres tömb, ha nincs raktári egyezés)",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StockMatchesResponse" } } }
          },
          "429": { "description": "Rate limit" }
        }
      }
    },
    "/api/items": {
      "get": {
        "tags": ["inventory"],
        "operationId": "listInventory",
        "summary": "Aktuális raktárkészlet bruttó árral",
        "description": "Kategóriánként csoportosított raktári tételek, kizárólag publikus mezőkkel (kiskereskedelmi ár + készlet).",
        "responses": {
          "200": {
            "description": "Készletlista",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InventoryResponse" } } }
          },
          "500": { "description": "Az upstream készlet nem elérhető" }
        }
      }
    },
    "/api/lp/lead": {
      "post": {
        "tags": ["lead"],
        "operationId": "submitQuoteRequest",
        "summary": "Ajánlatkérés / visszahívás beküldése",
        "description": "Ajánlatkérést rögzít és értesíti a céget. Munkatárs visszahívja az ügyfelet a megadott telefonszámon. A név és telefonszám kötelező.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LeadRequest" },
              "example": { "name": "Kovács Anna", "phone": "+36301234567", "email": "anna@example.com", "town": "Tiszafüred", "interest": "ablakcsere", "message": "2 db 120x150 ablak" }
            }
          }
        },
        "responses": {
          "200": { "description": "Rögzítve", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeadResponse" } } } },
          "400": { "description": "Hibás kérés (pl. hiányzó név/telefon)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit" }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "tags": ["mcp"],
        "operationId": "mcpJsonRpc",
        "summary": "MCP végpont (JSON-RPC 2.0, Streamable HTTP)",
        "description": "Model Context Protocol szerver AI-ágenseknek. JSON-RPC metódusok: initialize, tools/list, tools/call. Tool-ok: get_price_estimate, check_stock, list_inventory, request_quote (email-OTP megerősítéssel: a kód az ügyfél e-mailjére érkezik), confirm_quote (a kód beváltása — az ajánlatkérés csak ezután továbbítódik). A registry-ben: com.ablakunio/nyilaszaro-mcp.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "jsonrpc": { "type": "string", "const": "2.0" }, "id": {}, "method": { "type": "string" }, "params": { "type": "object" } }, "required": ["jsonrpc", "method"] },
              "example": { "jsonrpc": "2.0", "id": 1, "method": "tools/list" }
            }
          }
        },
        "responses": { "200": { "description": "JSON-RPC válasz", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    }
  },
  "components": {
    "schemas": {
      "ProductType": { "type": "string", "enum": ["window", "door", "shutter"], "description": "window=ablak, door=ajtó, shutter=redőny" },
      "PriceEstimateRequest": {
        "type": "object",
        "required": ["width", "height"],
        "properties": {
          "width": { "type": "number", "description": "Szélesség (az `unit` szerinti egységben; alapért. mm)" },
          "height": { "type": "number", "description": "Magasság (az `unit` szerinti egységben; alapért. mm)" },
          "unit": { "type": "string", "enum": ["mm", "cm"], "default": "mm" },
          "type": { "$ref": "#/components/schemas/ProductType" },
          "subtype": { "type": "string", "description": "pl. Erkélyajtó, Emelő-toló" },
          "glazing": { "type": "string", "enum": ["double", "triple"], "description": "2 vagy 3 rétegű üveg" },
          "color": { "type": "string", "description": "Szín, pl. Fehér, Antracit, Aranytölgy" },
          "colorExternal": { "type": "string" },
          "colorInternal": { "type": "string" },
          "profile": { "type": "string" },
          "hasShutter": { "type": "boolean" },
          "hasMosquitoNet": { "type": "boolean" }
        }
      },
      "PriceEstimateResponse": {
        "type": "object",
        "properties": {
          "price": { "type": "integer", "description": "Tájékoztató bruttó ár HUF-ban (darabár)" },
          "image": { "type": "string", "description": "A termék előnézeti képe data:image/png;base64 formában (nagy; ágensek figyelmen kívül hagyhatják)" },
          "param": { "type": "object", "description": "A számításhoz használt, normalizált paraméterek" }
        }
      },
      "StockCheckRequest": {
        "type": "object",
        "required": ["width", "height"],
        "properties": {
          "width": { "type": "number" },
          "height": { "type": "number" },
          "unit": { "type": "string", "enum": ["mm", "cm"], "default": "mm" },
          "type": { "$ref": "#/components/schemas/ProductType" },
          "color": { "type": "string" },
          "glazing": { "type": "string", "enum": ["double", "triple"] },
          "hasShutter": { "type": "boolean" },
          "hasInsulation": { "type": "boolean" }
        }
      },
      "StockMatchesResponse": {
        "type": "object",
        "properties": {
          "matches": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "exact": { "type": "boolean", "description": "Pontos méret-egyezés-e" },
                "item": {
                  "type": "object",
                  "description": "A raktári tétel (id, name, price_retail, inventory, méretek stb.)",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      },
      "InventoryItem": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "format": { "type": "string", "description": "Mértékegység, pl. db, fm" },
          "name": { "type": "string" },
          "price_retail": { "type": "integer", "description": "Bruttó kiskereskedelmi ár HUF" },
          "inventory": { "type": "number", "description": "Raktári mennyiség" }
        }
      },
      "InventoryResponse": {
        "type": "object",
        "properties": {
          "result": {
            "type": "object",
            "description": "Kategórianév -> (tétel-id -> tétel) beágyazott map",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": { "$ref": "#/components/schemas/InventoryItem" }
            }
          }
        }
      },
      "LeadRequest": {
        "type": "object",
        "required": ["name", "phone"],
        "properties": {
          "name": { "type": "string", "description": "Ügyfél neve" },
          "phone": { "type": "string", "description": "Telefonszám visszahíváshoz" },
          "email": { "type": "string", "format": "email" },
          "town": { "type": "string", "description": "Település" },
          "interest": { "type": "string", "description": "ablakcsere | bejarati_ajto | arnyekolas | egyeb" },
          "message": { "type": "string", "description": "Méretek, darabszám, egyéb igények" },
          "company_name": { "type": "string", "description": "B2B partner esetén" },
          "partner_type": { "type": "string", "description": "B2B partner típusa" }
        }
      },
      "LeadResponse": {
        "type": "object",
        "properties": { "success": { "type": "boolean" } }
      },
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string" } }
      }
    }
  }
}
