{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://assistente.segunor.internal/schemas/manifesto-ficha.json",
  "title": "Manifesto de ficha (compatível com inserir.php)",
  "description": "Schema exato do manifesto.json aceite por inserir.php (skill /inserir-funcionario). Ver 01-MANIFESTO.md para a explicação campo a campo.",
  "type": "object",
  "additionalProperties": false,
  "required": ["funcionario"],
  "properties": {
    "portal_submissao_id": {
      "type": "integer",
      "minimum": 0,
      "default": 0,
      "description": "0 = sem submissão do portal dos dados."
    },
    "readmissao": {
      "type": "boolean",
      "description": "true só quando o NIF já existe em funcionarios com estado Desativo. Omitir (não pôr false) no caso normal."
    },
    "funcionario": {
      "type": "object",
      "additionalProperties": false,
      "required": ["nome", "nif", "admissao", "mai"],
      "properties": {
        "nome": { "type": "string", "minLength": 1 },
        "nif": { "type": "string", "pattern": "^[0-9]{9}$" },
        "admissao": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", "description": "ISO YYYY-MM-DD, data real (checkdate). Vem da reserva, nunca se pergunta." },
        "mai": { "type": "string", "pattern": "^[0-9]{3,8}$" },

        "ncc": { "type": "string", "maxLength": 10, "description": "Só os 8 dígitos do CC (sem dígito de controlo nem letras/versão). Estrangeiro sem CC: nº do título de residência ou passaporte, sem checksum, cabe em varchar(10)." },
        "niss": { "type": "string", "pattern": "^$|^[0-9]{11}$", "description": "Checksum: pesos 29,23,19,17,13,11,7,5,3,2 sobre os 10 primeiros dígitos; controlo = (9 - soma%10) % 10." },
        "filho_de": { "type": "string", "description": "Pais separados por ' e ', NUNCA por ' * ' (o CC imprime *, a casa grava 'e')." },
        "nascimento": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "validade_cc": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },

        "especialidades": {
          "type": "string",
          "pattern": "^(VIG|SPR|ARD|ARE)(/(VIG|SPR|ARD|ARE))*$",
          "description": "Separadas por '/', NUNCA por vírgula (o script converte vírgula para / mas não confiar nisso). Só entram as especialidades confirmadas pelo utilizador a partir dos cartões PSP lidos, nunca inferidas da pasta."
        },
        "val_vig": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$", "description": "Só se o cartão VIG foi lido individualmente." },
        "val_spr": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "val_ard": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "val_are": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "val_outro": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },

        "morada": { "type": "string", "description": "Normalizada: '<Artéria> <Nome> nº<n>[ <compl>], <CP> <Localidade>'. Abreviaturas expandidas (R->Rua, Av->Avenida, Tv/Trav->Travessa, Pç/Pc->Praça, Lg->Largo, Estr->Estrada)." },
        "iban": { "type": "string", "pattern": "^$|^[A-Z]{2}[0-9]{2}[A-Z0-9]{10,30}$", "maxLength": 31, "description": "ISO 13616, qualquer país. Compacto ou com espaços de grupo em 4 no manifesto; o script grava sempre agrupado. Checksum mod-97 só automático para PT50." },
        "contacto": { "type": "string" },
        "email": { "type": "string", "pattern": "^$|^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" },

        "naturalidade": { "type": "string", "description": "RC novo (2026-09-01+) só traz 'Portugal' ou nada — não inventar freguesia/concelho." },
        "concelho": { "type": "string" },
        "distrito": { "type": "string", "description": "Derivado do concelho via ocr_distrito_de_concelho() do repo Sabichão; NUNCA da linha COMARCA." },
        "nacionalidade": { "type": "string" },

        "val_rc": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$", "description": "Data do 'CÓDIGO VIGENTE ATÉ', nunca a emissão. Exige finalidade 'exercício da atividade de segurança privada'." },
        "estado_civil": { "type": "string" },
        "ndependentes": { "type": "string", "pattern": "^[0-9]{1,2}$", "default": "0" },
        "habilitacoes": { "type": "string" },

        "zona1": { "type": "string", "description": "Da lista SELECT zona FROM zona WHERE estado='Ativo' na BD alvo (prod != dev)." },
        "zona2": { "type": "string" },
        "local_servico": { "type": "string" },
        "local_servico_ncontrato": { "type": "string", "description": "numero_contrato do cliente, para equipa_afetar. Vazio = sem afetação de equipa." },

        "nhoras": { "type": ["integer", "null"], "minimum": 0, "maximum": 744, "description": "null = não respondido -> nhoras=0, tipo_contrato vazio. Semanais no máx. 168." },
        "periodo_horas": { "type": "string", "enum": ["semanais", "mensais"], "default": "semanais" },

        "data_consulta": { "type": "string", "pattern": "^$|^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "notas": { "type": "string", "const": "", "description": "IGNORADO E ZERADO pelo script sempre — a skill nunca escreve nas notas do processo. Deixar sempre vazio." },
        "mec": { "type": "string", "description": "Normalmente vazio; o script recupera o MEC de um processo anterior automaticamente se existir." },

        "nome_emergencia": { "type": "string" },
        "contacto_emergencia": { "type": "string" },
        "relacao_emergencia": { "type": "string" },

        "rh_status": { "type": "string", "enum": ["Sim", "Não", "Adicionar"], "default": "Não", "description": "'Enviar' está fora do âmbito (envia email real de credenciais)." }
      }
    },

    "contrato_termo": {
      "type": ["object", "null"],
      "description": "null = modalidade não respondida -> não escreve processo_contrato.",
      "additionalProperties": false,
      "properties": {
        "modalidade": { "type": "string", "enum": ["termo_certo", "termo_incerto", "sem_termo"] },
        "data_inicio": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "duracao_meses": { "type": "integer", "minimum": 1, "maximum": 120 },
        "duracao_unidade": { "type": "string", "description": "Normalizada por contrato_duracao_unidade_norm(); default 'meses'." },
        "data_fim": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
        "renovavel": { "type": "string", "enum": ["0", "1"], "description": "String '1' para true (o script compara === '1'). Só relevante em termo_certo." },
        "renov_duracao": { "type": "integer", "minimum": 1, "maximum": 120 },
        "renov_duracao_unidade": { "type": "string" },
        "renov_previstas": { "type": "integer", "minimum": 1, "maximum": 9 },
        "motivo_termo": { "type": "string", "description": "Label completo de contrato_motivo_label(), ex. 'n.º2 h) Execução de obra, projeto ou atividade definida e temporária'. Obrigatório quando modalidade != sem_termo." }
      }
    },

    "condicoes": {
      "type": ["object", "null"],
      "description": "null = todos os defaults (tudo 0, dias 1,2,3,4,5).",
      "additionalProperties": false,
      "properties": {
        "recebe_horas_noturnas": { "type": "integer", "enum": [0, 1] },
        "recebe_horas_extra": { "type": "integer", "enum": [0, 1] },
        "recebe_feriados": { "type": "integer", "enum": [0, 1] },
        "fundo_desemprego_parcial": { "type": "integer", "enum": [0, 1] },
        "valor_fundo_desemprego": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]{1,2})?$" },
        "subsidio_ferias_duodecimos": { "type": "integer", "enum": [0, 1] },
        "subsidio_natal_duodecimos": { "type": "integer", "enum": [0, 1] },
        "quota_sindical": { "type": "integer", "enum": [0, 1] },
        "valor_quota_sindical": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]{1,2})?$" },
        "notas": { "type": "string", "description": "Notas internas das condições salariais (tabela diferente das notas do processo — esta não é zerada pelo script)." },
        "dias_trabalho": { "type": "array", "items": { "type": "integer", "minimum": 1, "maximum": 7 }, "uniqueItems": true },
        "usar_dias_trabalho": { "type": "integer", "enum": [0, 1] }
      }
    }
  }
}
