openapi: 3.0.3
info:
  title: Generatory numerów IT — API
  description: |
    REST API do generowania i walidacji formalnej numerów testowych (PL i wybrane EU).

    - **Autoryzacja:** wyłącznie `Authorization: Bearer <token>` (sekret w `config.php` / `API_TOKEN`).
    - **Brak wersjonowania** ścieżki (`/api/generate.php`).
    - **Bulk:** pole `options.count` (1–50); przy `count > 1` wypełniane jest `items[]`.
    - **Walidator:** `type: validate` z `options.targetType` i `options.value`.

    Numery są fikcyjne i przeznaczone wyłącznie do testów — nie należy ich traktować jako prawdziwych dokumentów.

    Przykłady wywołań (curl, PowerShell, JS): plik `docs/api-przyklady.md` w repozytorium.
  version: 1.0.0

servers:
  - url: https://generatory.g3web.pl
    description: Wdrożenie produkcyjne
    variables:
      host:
        default: generatory.g3web.pl
        description: Domena z konfiguracji wdrożenia

tags:
  - name: generate
    description: Generacja i walidacja

paths:
  /api/generate.php:
    options:
      tags: [generate]
      summary: CORS preflight
      description: Obsługa żądań cross-origin (np. SPA na innej domenie).
      responses:
        '204':
          description: Brak treści — dozwolone metody i nagłówki ustawione przez serwer
    post:
      tags: [generate]
      summary: Generuj lub waliduj
      description: |
        Jedyny endpoint biznesowy. Treść żądania to JSON z polami `type` i `options`.

        Opcjonalnie integracje mogą wysyłać `X-Source: api` (audyt — poza MVP).
      operationId: generate
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateRequest'
            examples:
              pesel:
                $ref: '#/components/examples/PeselGenerate'
              nipBulk:
                $ref: '#/components/examples/NipBulk'
              validate:
                $ref: '#/components/examples/ValidatePesel'
              testPerson:
                $ref: '#/components/examples/TestPerson'
              vin:
                $ref: '#/components/examples/VinGenerate'
              ibanEu:
                $ref: '#/components/examples/IbanEu'
              creditCard:
                $ref: '#/components/examples/CreditCard'
      responses:
        '200':
          description: Sukces
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerateSuccess'
              examples:
                pesel:
                  $ref: '#/components/examples/PeselSuccess'
                validateOk:
                  $ref: '#/components/examples/ValidateSuccess'
                bulk:
                  $ref: '#/components/examples/BulkSuccess'
        '400':
          description: Błąd żądania (brak type, zły JSON, nieznany type)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '401':
          description: Brak lub nieprawidłowy token Bearer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '405':
          description: Dozwolona jest tylko metoda POST
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '422':
          description: Nieprawidłowe parametry (np. data PESEL, nieobsługiwany kraj)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '500':
          description: Błąd serwera lub brak skonfigurowanego tokenu
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Token z `config.php` (`api_token`) lub zmiennej środowiskowej `API_TOKEN`.

  schemas:
    GeneratorType:
      type: string
      description: Identyfikator modułu generatora.
      enum:
        - pesel
        - nip
        - regon9
        - regon14
        - id-card
        - passport
        - bank-account
        - validate
        - test-person
        - driving-license
        - vin
        - residence-card
        - iban-eu
        - vat-eu
        - credit-card

    GenerateRequest:
      type: object
      required: [type]
      properties:
        type:
          $ref: '#/components/schemas/GeneratorType'
        options:
          $ref: '#/components/schemas/GeneratorOptions'

    GeneratorOptions:
      type: object
      description: |
        Wszystkie pola są opcjonalne; znaczenie zależy od `type`.
        Nieznane klucze są ignorowane przez większość generatorów.
      properties:
        count:
          type: integer
          minimum: 1
          maximum: 50
          default: 1
          description: Liczba wyników (poza `validate` — zawsze jeden wynik).
        birthDate:
          type: string
          format: date
          description: Data urodzenia `YYYY-MM-DD` (PESEL, test-person). Strefa interpretacji — Europe/Warsaw.
        age:
          type: integer
          minimum: 0
          maximum: 250
          description: Wiek w latach zamiast `birthDate` (PESEL, test-person).
        gender:
          type: string
          enum: [any, male, female]
          default: any
          description: Płeć (PESEL, test-person).
        formatStyle:
          type: string
          enum: [plain, dashes, spaces]
          description: |
            - `nip`: plain | dashes (np. 123-456-78-90)
            - `regon9` / `regon14`: spaces — spacja po 9 cyfrach dla REGON-14
        useSpace:
          type: boolean
          description: Spacja między serią a numerem (dowód, paszport, test-person).
        series:
          type: string
          minLength: 3
          maxLength: 3
          description: Stała seria dowodu (3 litery); inaczej losowa.
        format:
          type: string
          enum: [iban, nrb]
          default: iban
          description: Rachunek PL — IBAN lub sam NRB (26 cyfr).
        grouped:
          type: boolean
          description: Grupowanie cyfr (rachunek PL, IBAN EU).
        groupSize:
          type: integer
          minimum: 2
          maximum: 8
          default: 4
          description: Rozmiar grupy przy `grouped` / `formatted`.
        ibanPrefix:
          type: boolean
          default: true
          description: Rachunek PL — zachowanie formatu IBAN (meta).
        manufacturer:
          type: string
          description: |
            VIN — `any` lub identyfikator producenta z katalogu WMI (np. `volkswagen`, `bmw`).
            Lista w UI / `VinWmiCatalog`.
        formatSpaced:
          type: boolean
          description: Prawo jazdy PL — spacja po prefiksie PL.
        output:
          type: string
          enum: [document-number, mrz-line1]
          default: document-number
          description: Karta pobytu — numer dokumentu lub linia MRZ (30 znaków).
        country:
          type: string
          minLength: 2
          maxLength: 2
          description: |
            Kod ISO kraju (wielkie litery).
            - `iban-eu`: patrz `IbanCountrySpec` (np. DE, PL, GB…)
            - `vat-eu`: PL, CZ, SK, DE, AT, BE, NL, IT, HU, LU, FR, SE, DK, FI, EE, LV, RO, BG, HR, SI
        formatted:
          type: boolean
          description: IBAN EU — grupowanie znaków (`groupSize`, domyślnie 4).
        issuer:
          type: string
          description: |
            Karta kredytowa — `any` lub id wystawcy:
            visa, mastercard, amex, discover, diners, jcb, unionpay, maestro, mir, elo, hipercard,
            visa-electron, dankort, carte-bancaire, uatp
        withCvv:
          type: boolean
          description: Karta — dołącz `cvv`, `expiryMonth`, `expiryYear` w `meta`.
        outputFormat:
          type: string
          enum: [json, lines]
          default: json
          description: test-person — format pola `formatted`.
        bankFormat:
          type: string
          enum: [iban, nrb]
          description: test-person — alias formatu rachunku w pakiecie.
        targetType:
          $ref: '#/components/schemas/GeneratorType'
          description: Walidator — typ numeru do sprawdzenia (alias `type` w options).
        value:
          type: string
          description: Walidator — numer do sprawdzenia (dowolne formatowanie/spacje).

    GenerateItem:
      type: object
      required: [value, formatted, meta]
      properties:
        value:
          type: string
          description: Wartość kanoniczna (bez zbędnych separatorów, z wyjątkiem test-person lines).
        formatted:
          type: string
          description: Wartość do wyświetlenia / kopiowania.
        meta:
          type: object
          additionalProperties: true
          description: Metadane zależne od typu (data urodzenia, kraj, wynik walidacji…).

    GenerateSuccess:
      type: object
      required: [ok, type, value, formatted, meta, items]
      properties:
        ok:
          type: boolean
          enum: [true]
        type:
          $ref: '#/components/schemas/GeneratorType'
        value:
          type: string
        formatted:
          type: string
        meta:
          type: object
          additionalProperties: true
        items:
          type: array
          description: Pusta tablica przy `count` = 1; przy bulk — pełna lista elementów.
          items:
            $ref: '#/components/schemas/GenerateItem'

    ApiError:
      type: object
      required: [ok, error, message]
      properties:
        ok:
          type: boolean
          enum: [false]
        error:
          type: string
          description: |
            Kody m.in.: `unauthorized`, `missing_type`, `unknown_type`, `invalid_json`,
            `invalid_body`, `method_not_allowed`, `server_error`, `server_misconfigured`,
            oraz kody walidacji parametrów: `invalid_birth_date`, `unsupported_country`, `unsupported_issuer`.
        message:
          type: string
          description: Komunikat po polsku.

    ValidateMeta:
      type: object
      properties:
        valid:
          type: boolean
        errors:
          type: array
          items:
            type: string
        parsed:
          type: object
          additionalProperties: true

  examples:
    PeselGenerate:
      summary: PESEL z datą urodzenia
      value:
        type: pesel
        options:
          birthDate: '1990-05-15'
          gender: female
          count: 1

    NipBulk:
      summary: 5 numerów NIP
      value:
        type: nip
        options:
          formatStyle: dashes
          count: 5

    ValidatePesel:
      summary: Walidacja PESEL
      value:
        type: validate
        options:
          targetType: pesel
          value: '90051500842'

    TestPerson:
      summary: Pakiet osoba testowa (JSON)
      value:
        type: test-person
        options:
          gender: male
          outputFormat: json

    VinGenerate:
      summary: VIN dla producenta
      value:
        type: vin
        options:
          manufacturer: volkswagen
          count: 1

    IbanEu:
      summary: IBAN Niemcy
      value:
        type: iban-eu
        options:
          country: DE
          formatted: true
          groupSize: 4

    CreditCard:
      summary: Karta Visa z CVV
      value:
        type: credit-card
        options:
          issuer: visa
          formatted: true
          withCvv: true

    PeselSuccess:
      summary: Odpowiedź PESEL
      value:
        ok: true
        type: pesel
        value: '90051500842'
        formatted: '90051500842'
        meta:
          birthDate: '1990-05-15'
          gender: female
        items: []

    ValidateSuccess:
      summary: Walidacja poprawna
      value:
        ok: true
        type: validate
        value: '90051500842'
        formatted: '90051500842'
        meta:
          valid: true
          errors: []
          parsed:
            birthDate: '1990-05-15'
            gender: female
        items: []

    BulkSuccess:
      summary: Bulk NIP (fragment)
      value:
        ok: true
        type: nip
        value: '5261040828'
        formatted: '526-104-08-28'
        meta: {}
        items:
          - value: '5261040828'
            formatted: '526-104-08-28'
            meta: {}
          - value: '1132335790'
            formatted: '113-233-57-90'
            meta: {}
