{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://visadanet.ru/api/v1/schema.json",
  "title": "ВизаДаНет — запись страны",
  "description": "Правила въезда в страну для граждан РФ. Запись после слияния с файлом группы. Даты — ISO 8601, суммы — число плюс код валюты ISO 4217.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version", "citizenship", "iso2", "name_ru", "name_ru_to", "slug", "region",
    "status", "verified_at", "sources", "evidence", "confidence"
  ],
  "properties": {
    "schema_version": { "const": 1 },
    "citizenship": { "const": "RU" },
    "published": {
      "type": "boolean",
      "description": "true — запись выверена человеком по двум T1 и показывается на сайте без пометки «черновик»"
    },

    "iso2": { "type": "string", "pattern": "^[A-Z]{2}$" },
    "name_ru": { "type": "string", "minLength": 2 },
    "name_ru_to": { "type": "string", "description": "куда: «в Таиланд», «на Кубу»" },
    "name_ru_in": { "type": "string", "description": "где: «в Таиланде», «на Кубе»" },
    "slug": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
    "region": { "enum": ["near_abroad", "middle_east_africa", "asia", "europe", "americas_oceania"] },
    "group": { "type": ["string", "null"], "enum": ["schengen", "eaeu", "gcc", null] },

    "status": { "$ref": "#/$defs/status" },
    "status_valid_until": {
      "type": ["string", "null"], "format": "date",
      "description": "срочный режим: до какой даты действует текущий статус (безвиз с Китаем до 31.12.2027)"
    },
    "stay_days": { "type": ["integer", "null"], "minimum": 1, "maximum": 365 },
    "stay_limit": {
      "type": ["object", "null"],
      "description": "накопительный лимит: 90 дней за 180, 90 в год",
      "additionalProperties": false,
      "required": ["days", "period_days"],
      "properties": {
        "days": { "type": "integer", "minimum": 1, "maximum": 365 },
        "period_days": { "type": "integer", "minimum": 1, "maximum": 730 }
      }
    },
    "entries_limit": { "type": ["integer", "null"], "minimum": 1 },
    "extension": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "required": ["possible"],
      "properties": {
        "possible": { "type": "boolean" },
        "days": { "type": ["integer", "null"], "minimum": 1, "maximum": 365 },
        "fee": { "$ref": "#/$defs/money_or_null" },
        "where": { "type": "string" }
      }
    },
    "purpose": {
      "type": "array",
      "items": { "enum": ["tourism", "transit", "business", "private", "any"] },
      "uniqueItems": true
    },
    "options": {
      "type": "array",
      "description": "альтернативные пути въезда (например, e-виза при безвизе на 30 дней)",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["status", "summary"],
        "properties": {
          "status": { "$ref": "#/$defs/status" },
          "summary": { "type": "string" },
          "stay_days": { "type": ["integer", "null"], "minimum": 1, "maximum": 365 },
          "fee": { "$ref": "#/$defs/money_or_null" },
          "url": { "type": "string", "format": "uri" }
        }
      }
    },

    "visa": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "properties": {
        "type": { "type": "string" },
        "fee": { "$ref": "#/$defs/money_or_null" },
        "service_fee": { "$ref": "#/$defs/money_or_null" },
        "processing_days": { "type": ["integer", "null"], "minimum": 0, "maximum": 180 },
        "apply_before_days": { "type": ["integer", "null"], "minimum": 0, "maximum": 365 },
        "apply_max_before_days": { "type": ["integer", "null"], "minimum": 0, "maximum": 365 },
        "where": { "type": "string" },
        "where_url": { "type": "string", "format": "uri" },
        "biometric_passport_required": { "type": ["boolean", "null"] }
      }
    },

    "pre_arrival": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "name"],
        "properties": {
          "kind": { "enum": ["arrival_card", "eta", "e_registration", "biometric_registration", "health_declaration", "other"] },
          "name": { "type": "string" },
          "summary": { "type": "string" },
          "deadline_hours_before": {
            "type": ["integer", "null"], "minimum": 0,
            "description": "окно подачи открывается за столько часов до прибытия: «не раньше чем за 3 дня» → 72"
          },
          "url": { "type": "string", "format": "uri" },
          "fee": { "$ref": "#/$defs/money_or_null" }
        }
      }
    },

    "passport": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "properties": {
        "validity_months": { "type": ["integer", "null"], "minimum": 0, "maximum": 24 },
        "validity_basis": { "enum": ["entry", "exit", null], "description": "считается от даты въезда или выезда" },
        "blank_pages": { "type": ["integer", "null"], "minimum": 0, "maximum": 10 },
        "issued_within_years": { "type": ["integer", "null"], "minimum": 1, "maximum": 20 },
        "internal_passport_ok": { "type": ["boolean", "null"] },
        "old_passport_accepted": { "type": ["boolean", "null"] }
      }
    },

    "border": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "properties": {
        "return_ticket": { "type": ["boolean", "null"] },
        "accommodation_proof": { "type": ["boolean", "null"] },
        "funds_proof": {
          "type": ["object", "null"],
          "additionalProperties": false,
          "required": ["amount", "currency"],
          "properties": {
            "amount": { "type": "number", "minimum": 0 },
            "currency": { "$ref": "#/$defs/currency" },
            "per": { "enum": ["person", "family", "day", "trip"] }
          }
        },
        "insurance_required": { "type": ["boolean", "null"] },
        "insurance_min": { "$ref": "#/$defs/money_or_null" },
        "entry_points": {
          "type": ["object", "null"],
          "additionalProperties": false,
          "required": ["restriction"],
          "properties": {
            "restriction": { "enum": ["none", "airports_only", "listed_only"] },
            "note": { "type": "string" }
          }
        },
        "ees": { "type": ["boolean", "null"], "description": "биометрическая регистрация в Entry/Exit System Шенгена" }
      }
    },

    "fees": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "amount", "currency"],
        "properties": {
          "kind": { "enum": ["tourist_tax", "entry_fee", "exit_fee", "visa_fee", "service_fee", "other"] },
          "amount": { "type": "number", "minimum": 0 },
          "currency": { "$ref": "#/$defs/currency" },
          "note": { "type": "string" }
        }
      }
    },
    "payments": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "properties": {
        "mir": { "type": ["boolean", "null"] },
        "unionpay": { "type": ["boolean", "null"] },
        "cash_advice": { "type": "string" }
      }
    },

    "planned_change": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "required": ["direction", "summary", "confidence", "source"],
      "properties": {
        "direction": { "enum": ["easing", "tightening", "neutral"] },
        "summary": { "type": "string" },
        "expected_date": { "type": ["string", "null"], "format": "date" },
        "confidence": { "$ref": "#/$defs/confidence" },
        "source": { "type": "string", "description": "id из sources" }
      }
    },
    "effective_from": {
      "type": ["object", "null"],
      "description": "уже принятое правило с будущей датой; переключается по календарю",
      "additionalProperties": false,
      "required": ["date", "summary", "changes"],
      "properties": {
        "date": { "type": "string", "format": "date" },
        "summary": { "type": "string" },
        "changes": { "type": "object", "description": "поля записи, которые примут новые значения в эту дату" }
      }
    },

    "verified_at": { "type": "string", "format": "date" },
    "changed_at": {
      "type": ["string", "null"], "format": "date",
      "description": "когда правило последний раз изменилось; null — дата не подтверждена источником"
    },
    "confidence": { "$ref": "#/$defs/confidence" },
    "review_notes": { "type": ["string", "null"] },
    "sources": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "tier", "url", "title"],
        "properties": {
          "id": { "type": "string", "pattern": "^[a-z0-9_]+$" },
          "tier": { "$ref": "#/$defs/tier" },
          "url": { "type": "string", "format": "uri" },
          "title": { "type": "string" },
          "fetched_at": { "type": ["string", "null"], "format": "date" },
          "excerpt_hash": { "type": ["string", "null"] }
        }
      }
    },
    "evidence": {
      "type": "object",
      "description": "путь поля (status, visa.fee, border.funds_proof) → подтверждения с дословной цитатой",
      "additionalProperties": {
        "type": "array",
        "minItems": 1,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": ["source", "quote"],
          "properties": {
            "source": { "type": "string" },
            "quote": { "type": "string", "minLength": 3 },
            "snippet_only": { "type": "boolean", "description": "цитата из поисковой выдачи, страница не прочитана" }
          }
        }
      }
    }
  },

  "$defs": {
    "status": { "enum": ["visa_free", "evisa", "visa_on_arrival", "visa_required", "restricted", "unclear"] },
    "confidence": { "enum": ["high", "medium", "low"] },
    "tier": { "enum": ["T1_ru", "T1_country", "T2", "T3"] },
    "currency": { "type": "string", "pattern": "^[A-Z]{3}$" },
    "money_or_null": {
      "type": ["object", "null"],
      "additionalProperties": false,
      "required": ["amount", "currency"],
      "properties": {
        "amount": { "type": "number", "minimum": 0 },
        "currency": { "$ref": "#/$defs/currency" }
      }
    }
  }
}
