from __future__ import annotations

from agrobr.contracts import (
    BreakingChangePolicy,
    Column,
    ColumnType,
    Contract,
    register_contract,
)

CREDITO_RURAL_V1_1 = Contract(
    name="bcb.credito_rural",
    version="1.1",
    effective_from="0.10.1",
    primary_key=["safra", "produto", "uf", "finalidade"],
    columns=[
        Column(
            name="safra",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="finalidade",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="agregacao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="volume",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="cd_programa",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="programa",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="cd_fonte_recurso",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="fonte_recurso",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="cd_tipo_seguro",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="tipo_seguro",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="cd_modalidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="modalidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="cd_atividade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="atividade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="regiao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'safra' always matches pattern YYYY/YY",
        "'uf' is always a valid Brazilian state code when present",
        "Numeric values are always >= 0",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

EXPORTACAO_V1 = Contract(
    name="comexstat.exportacao",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["ano", "mes", "produto", "uf"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1997,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="kg_liquido",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_fob_usd",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 1997",
        "'mes' is between 1 and 12",
        "Numeric values are always >= 0",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

FERTILIZANTE_V1 = Contract(
    name="anda.fertilizante",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["ano", "mes", "uf", "produto_fertilizante"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2000,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="produto_fertilizante",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="volume_ton",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 2000",
        "'mes' is between 1 and 12",
        "Numeric values are always >= 0",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

FOCOS_QUEIMADAS_V1 = Contract(
    name="queimadas.focos",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["data", "lat", "lon", "satelite", "hora_gmt"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
        ),
        Column(
            name="hora_gmt",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="lat",
            type=ColumnType.FLOAT,
            nullable=False,
            stable=True,
            min_value=-35.0,
            max_value=6.0,
        ),
        Column(
            name="lon",
            type=ColumnType.FLOAT,
            nullable=False,
            stable=True,
            min_value=-74.0,
            max_value=-30.0,
        ),
        Column(
            name="satelite",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="municipio_id",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
        ),
        Column(
            name="estado",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="bioma",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="numero_dias_sem_chuva",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="precipitacao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="mm",
            stable=True,
            min_value=0,
        ),
        Column(
            name="risco_fogo",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
            max_value=1,
        ),
        Column(
            name="frp",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="MW",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'lat' is always between -35 and 6 (Brazil bounding box)",
        "'lon' is always between -74 and -30 (Brazil bounding box)",
        "'data' is always a valid date",
        "Numeric values are always >= 0 when present",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

DESMATAMENTO_PRODES_V1 = Contract(
    name="desmatamento.prodes",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["ano", "uf", "classe", "bioma"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2000,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="area_km2",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="km2",
            stable=True,
            min_value=0,
        ),
        Column(
            name="satelite",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="sensor",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="bioma",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 2000",
        "'area_km2' is always >= 0",
        "'uf' is always a valid Brazilian state code",
        "'bioma' is always a valid Brazilian biome name",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

DESMATAMENTO_DETER_V1 = Contract(
    name="desmatamento.deter",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["data", "classe", "uf", "municipio", "bioma"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="municipio_id",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
        ),
        Column(
            name="area_km2",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="km2",
            stable=True,
            min_value=0,
        ),
        Column(
            name="satelite",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="sensor",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="bioma",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'data' is always a valid date",
        "'area_km2' is always >= 0",
        "'uf' is always a valid Brazilian state code",
        "'bioma' is always 'Amazônia' or 'Cerrado'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

MAPBIOMAS_COBERTURA_V1 = Contract(
    name="mapbiomas.cobertura",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["bioma", "estado", "classe_id", "ano"],
    columns=[
        Column(
            name="bioma",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="estado",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe_id",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="nivel_0",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1985,
        ),
        Column(
            name="area_ha",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="ha",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'bioma' is always a valid Brazilian biome name",
        "'estado' is always a valid Brazilian state code (UF)",
        "'ano' is always between 1985 and current year",
        "'area_ha' is always >= 0",
        "'classe_id' maps to MapBiomas LULC legend codes",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

MAPBIOMAS_TRANSICAO_V1 = Contract(
    name="mapbiomas.transicao",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["bioma", "estado", "classe_de_id", "classe_para_id", "periodo"],
    columns=[
        Column(
            name="bioma",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="estado",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe_de_id",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe_de",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe_para_id",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
        ),
        Column(
            name="classe_para",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="periodo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="area_ha",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="ha",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'bioma' is always a valid Brazilian biome name",
        "'estado' is always a valid Brazilian state code (UF)",
        "'periodo' always matches pattern YYYY-YYYY",
        "'area_ha' is always >= 0",
        "'classe_de_id' and 'classe_para_id' map to MapBiomas LULC legend codes",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

CONAB_PROGRESSO_V1 = Contract(
    name="conab.progresso_safra",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["cultura", "safra", "operacao", "estado", "semana_atual"],
    columns=[
        Column(
            name="cultura",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
            description="Cultura (ex: Soja, Milho 2a)",
        ),
        Column(
            name="safra",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
            description="Safra no formato YYYY/YY",
        ),
        Column(
            name="operacao",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
            description="Semeadura ou Colheita",
        ),
        Column(
            name="estado",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
            description="Codigo UF (ex: MT, GO, PR)",
        ),
        Column(
            name="semana_atual",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
            description="Data da semana no formato YYYY-MM-DD",
        ),
        Column(
            name="pct_ano_anterior",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            unit="fracao",
            min_value=0.0,
            max_value=1.0,
        ),
        Column(
            name="pct_semana_anterior",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            unit="fracao",
            min_value=0.0,
            max_value=1.0,
        ),
        Column(
            name="pct_semana_atual",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            unit="fracao",
            min_value=0.0,
            max_value=1.0,
        ),
        Column(
            name="pct_media_5_anos",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            unit="fracao",
            min_value=0.0,
            max_value=1.0,
        ),
    ],
    guarantees=[
        "PK unica por combinacao cultura + safra + operacao + estado + semana",
        "Valores percentuais entre 0.0 e 1.0 (fracao, nao %)",
        "Dados semanais publicados pela CONAB",
        "'estado' e codigo UF de 2 letras (ex: MT, GO, PR)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

AJUSTE_DIARIO_V1 = Contract(
    name="b3.ajuste_diario",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["data", "ticker", "vencimento_codigo"],
    columns=[
        Column(name="data", type=ColumnType.DATE, nullable=False, stable=True),
        Column(name="ticker", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="descricao", type=ColumnType.STRING, nullable=True, stable=True),
        Column(
            name="vencimento_codigo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="vencimento_mes",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="vencimento_ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2000,
        ),
        Column(
            name="ajuste_anterior",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="ajuste_atual",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(name="variacao", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(
            name="ajuste_por_contrato",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
        ),
        Column(name="unidade", type=ColumnType.STRING, nullable=True, stable=True),
    ],
    guarantees=[
        "PK unica por combinacao data + ticker + vencimento_codigo",
        "'ticker' sempre em {BGI, CCM, ICF, CNL, ETH, SJC, SOY}",
        "'vencimento_mes' entre 1 e 12",
        "'ajuste_atual' e 'ajuste_anterior' sempre >= 0 quando presentes",
        "Dados apenas para dias uteis (sem pregao em weekends/feriados)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

PRECO_ATACADO_V1 = Contract(
    name="conab.preco_atacado",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["data", "produto", "ceasa"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="categoria",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="unidade",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="ceasa",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="ceasa_uf",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="preco",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "PK unica por combinacao data + produto + ceasa",
        "'produto' sempre em maiusculas (ex: TOMATE, ABACAXI)",
        "'categoria' sempre FRUTAS ou HORTALICAS",
        "'unidade' sempre KG, UN ou DZ",
        "'ceasa_uf' sempre codigo UF de 2 letras",
        "'preco' sempre > 0 (nulls filtrados)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

POSICOES_ABERTAS_V1 = Contract(
    name="b3.posicoes_abertas",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["data", "ticker_completo"],
    columns=[
        Column(name="data", type=ColumnType.DATE, nullable=False, stable=True),
        Column(name="ticker", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="descricao", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="ticker_completo", type=ColumnType.STRING, nullable=False, stable=True),
        Column(
            name="vencimento_codigo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="vencimento_mes",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="vencimento_ano",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=2000,
        ),
        Column(name="tipo", type=ColumnType.STRING, nullable=False, stable=True),
        Column(
            name="posicoes_abertas",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=0,
        ),
        Column(name="variacao_posicoes", type=ColumnType.INTEGER, nullable=True, stable=True),
        Column(name="unidade", type=ColumnType.STRING, nullable=True, stable=True),
    ],
    guarantees=[
        "PK unica por combinacao data + ticker_completo",
        "'ticker' sempre em {BGI, CCM, ETH, ICF, SJC, CNL}",
        "'tipo' sempre 'futuro' ou 'opcao'",
        "'posicoes_abertas' sempre >= 0",
        "Dados apenas para dias uteis (sem pregao em weekends/feriados)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

COMERCIO_BILATERAL_V1 = Contract(
    name="comtrade.comercio",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["periodo", "reporter_iso", "partner_iso", "hs_code", "fluxo_code"],
    columns=[
        Column(
            name="periodo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1988,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="reporter_iso",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="reporter",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="partner_iso",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="partner",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="fluxo_code",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="hs_code",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="produto_desc",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="peso_liquido_kg",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
            min_value=0,
        ),
        Column(
            name="volume_ton",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_fob_usd",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_cif_usd",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_primario_usd",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 1988",
        "'mes' is between 1 and 12 when present",
        "Numeric values are always >= 0 when present",
        "'fluxo_code' is always 'X' (export) or 'M' (import)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

TRADE_MIRROR_V1 = Contract(
    name="comtrade.trade_mirror",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["periodo", "hs_code", "reporter_iso", "partner_iso"],
    columns=[
        Column(
            name="periodo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1988,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="hs_code",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="produto_desc",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="reporter_iso",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="partner_iso",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="peso_liquido_kg_reporter",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_fob_usd_reporter",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
        Column(
            name="volume_ton_reporter",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
        Column(
            name="peso_liquido_kg_partner",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_fob_usd_partner",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_cif_usd_partner",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
            min_value=0,
        ),
        Column(
            name="volume_ton_partner",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
        Column(
            name="diff_peso_kg",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
        ),
        Column(
            name="diff_valor_fob_usd",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="USD",
            stable=True,
        ),
        Column(
            name="ratio_valor",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
        ),
        Column(
            name="ratio_peso",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 1988",
        "'mes' is between 1 and 12 when present",
        "Mirror compares reporter exports (FOB) vs partner imports (CIF)",
        "'ratio_valor' expected range ~0.85-0.95 for normal trade (FOB/CIF)",
        "'ratio_peso' expected ~1.0 for normal trade",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

MOVIMENTACAO_PORTUARIA_V1 = Contract(
    name="antaq.movimentacao",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["ano", "mes", "porto", "cd_mercadoria", "sentido", "tipo_navegacao"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2010,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="data_atracacao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="tipo_navegacao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="tipo_operacao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="natureza_carga",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="sentido",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="porto",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="complexo_portuario",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="terminal",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="regiao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="cd_mercadoria",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="mercadoria",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="grupo_mercadoria",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="origem",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="destino",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="peso_bruto_ton",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
        Column(
            name="qt_carga",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="teu",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always >= 2010",
        "'mes' is between 1 and 12",
        "'uf' is always a valid Brazilian state code when present",
        "'sentido' is always 'Embarcados' or 'Desembarcados' when present",
        "'peso_bruto_ton' is always >= 0 when present",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("ajuste_diario", AJUSTE_DIARIO_V1)
register_contract("conab_progresso", CONAB_PROGRESSO_V1)
register_contract("preco_atacado", PRECO_ATACADO_V1)
register_contract("credito_rural", CREDITO_RURAL_V1_1)
register_contract("desmatamento_prodes", DESMATAMENTO_PRODES_V1)
register_contract("desmatamento_deter", DESMATAMENTO_DETER_V1)
register_contract("exportacao", EXPORTACAO_V1)
register_contract("fertilizante", FERTILIZANTE_V1)
register_contract("focos_queimadas", FOCOS_QUEIMADAS_V1)
register_contract("mapbiomas_cobertura", MAPBIOMAS_COBERTURA_V1)
register_contract("mapbiomas_transicao", MAPBIOMAS_TRANSICAO_V1)
register_contract("comercio_bilateral", COMERCIO_BILATERAL_V1)
register_contract("movimentacao_portuaria", MOVIMENTACAO_PORTUARIA_V1)
register_contract("trade_mirror", TRADE_MIRROR_V1)
register_contract("posicoes_abertas", POSICOES_ABERTAS_V1)

ANP_DIESEL_PRECOS_V1 = Contract(
    name="anp_diesel.precos",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["data", "uf", "municipio", "produto"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="preco_venda",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL/litro",
            stable=True,
            min_value=0,
        ),
        Column(
            name="preco_compra",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL/litro",
            stable=True,
            min_value=0,
        ),
        Column(
            name="margem",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL/litro",
            stable=True,
        ),
        Column(
            name="n_postos",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'uf' is a valid Brazilian state code when present",
        "'produto' is always 'DIESEL' or 'DIESEL S10'",
        "'preco_venda' and 'preco_compra' are in BRL/litro when present",
        "'margem' equals preco_venda - preco_compra",
        "Data is weekly (date of collection)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

ANP_DIESEL_VENDAS_V1 = Contract(
    name="anp_diesel.vendas",
    version="1.0",
    effective_from="0.11.0",
    primary_key=["data", "uf", "produto"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="regiao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="volume_m3",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="m3",
            stable=True,
            min_value=0,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'uf' is a valid Brazilian state code when present",
        "'volume_m3' is in cubic meters when present",
        "Data is monthly (first day of month)",
        "'produto' contains DIESEL variants only",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("anp_diesel_precos", ANP_DIESEL_PRECOS_V1)
register_contract("anp_diesel_vendas", ANP_DIESEL_VENDAS_V1)

MAPA_PSR_SINISTROS_V1 = Contract(
    name="mapa_psr.sinistros",
    version="1.0",
    effective_from="0.12.0",
    primary_key=["nr_apolice", "ano_apolice", "uf", "cultura", "cd_ibge", "evento"],
    columns=[
        Column(name="nr_apolice", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="ano_apolice", type=ColumnType.INTEGER, nullable=False, stable=True),
        Column(name="uf", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="municipio", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="cd_ibge", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="cultura", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="classificacao", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="evento", type=ColumnType.STRING, nullable=False, stable=True),
        Column(
            name="area_total",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_indenizacao",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_premio",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_subvencao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_limite_garantia",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(name="produtividade_estimada", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="produtividade_segurada", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="nivel_cobertura", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="seguradora", type=ColumnType.STRING, nullable=True, stable=True),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'uf' is a valid Brazilian state code",
        "'valor_indenizacao' is always > 0 (sinistros only)",
        "'evento' is always non-empty (sinistros only)",
        "Monetary values are in BRL",
        "Data since 2006 (PSR inception)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

MAPA_PSR_APOLICES_V1 = Contract(
    name="mapa_psr.apolices",
    version="1.0",
    effective_from="0.12.0",
    primary_key=["nr_apolice", "ano_apolice", "uf", "cultura", "cd_ibge"],
    columns=[
        Column(name="nr_apolice", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="ano_apolice", type=ColumnType.INTEGER, nullable=False, stable=True),
        Column(name="uf", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="municipio", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="cd_ibge", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="cultura", type=ColumnType.STRING, nullable=False, stable=True),
        Column(name="classificacao", type=ColumnType.STRING, nullable=True, stable=True),
        Column(
            name="area_total",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_premio",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_subvencao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_limite_garantia",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_indenizacao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="BRL",
            stable=True,
            min_value=0,
        ),
        Column(name="evento", type=ColumnType.STRING, nullable=True, stable=True),
        Column(name="produtividade_estimada", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="produtividade_segurada", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="nivel_cobertura", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="taxa", type=ColumnType.FLOAT, nullable=True, stable=True),
        Column(name="seguradora", type=ColumnType.STRING, nullable=True, stable=True),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'uf' is a valid Brazilian state code",
        "All policies with federal subsidy since 2006",
        "'valor_indenizacao' is nullable (0 or null if no claim)",
        "Monetary values are in BRL",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("mapa_psr_sinistros", MAPA_PSR_SINISTROS_V1)
register_contract("mapa_psr_apolices", MAPA_PSR_APOLICES_V1)

ANTT_PEDAGIO_FLUXO_V1 = Contract(
    name="antt_pedagio.fluxo",
    version="1.0",
    effective_from="0.12.0",
    primary_key=["data", "concessionaria", "praca", "sentido", "n_eixos"],
    columns=[
        Column(
            name="data",
            type=ColumnType.DATE,
            nullable=False,
            stable=True,
            description="1o dia do mes",
        ),
        Column(
            name="concessionaria",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="praca",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="sentido",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
            description="Crescente/Decrescente",
        ),
        Column(
            name="n_eixos",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2,
            max_value=18,
            description="Numero de eixos do veiculo (2-18)",
        ),
        Column(
            name="tipo_veiculo",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
            description="Passeio/Comercial/Moto",
        ),
        Column(
            name="volume",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=0,
            description="Volume de veiculos no mes",
        ),
        Column(
            name="rodovia",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
            description="Rodovia (do join com cadastro de pracas)",
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
            description="UF (do join com cadastro de pracas)",
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
            description="Municipio (do join com cadastro de pracas)",
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'data' is always the 1st day of the month",
        "'n_eixos' is always between 2 and 18",
        "'volume' is always >= 0",
        "'uf' is a valid Brazilian state code when present",
        "'tipo_veiculo' is always Passeio, Comercial, or Moto when present",
        "Data since 2010 (ANTT open data inception)",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

ANTT_PEDAGIO_PRACAS_V1 = Contract(
    name="antt_pedagio.pracas",
    version="1.0",
    effective_from="0.12.0",
    primary_key=["concessionaria", "praca_de_pedagio"],
    columns=[
        Column(
            name="concessionaria",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="praca_de_pedagio",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="rodovia",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="km_m",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="lat",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=-35.0,
            max_value=6.0,
        ),
        Column(
            name="lon",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=-74.0,
            max_value=-30.0,
        ),
        Column(
            name="situacao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'uf' is a valid Brazilian state code when present",
        "'lat' is within Brazil bounding box when present",
        "'lon' is within Brazil bounding box when present",
        "200+ toll plazas registered",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("antt_pedagio_fluxo", ANTT_PEDAGIO_FLUXO_V1)
register_contract("antt_pedagio_pracas", ANTT_PEDAGIO_PRACAS_V1)

SICAR_IMOVEIS_V1 = Contract(
    name="sicar.imoveis",
    version="1.0",
    effective_from="0.12.0",
    primary_key=["cod_imovel"],
    columns=[
        Column(
            name="cod_imovel",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="status",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="data_criacao",
            type=ColumnType.DATETIME,
            nullable=False,
            stable=True,
        ),
        Column(
            name="data_atualizacao",
            type=ColumnType.DATETIME,
            nullable=True,
            stable=True,
        ),
        Column(
            name="area_ha",
            type=ColumnType.FLOAT,
            nullable=False,
            unit="ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="condicao",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="uf",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="municipio",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="cod_municipio_ibge",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
        ),
        Column(
            name="modulos_fiscais",
            type=ColumnType.FLOAT,
            nullable=False,
            stable=True,
            min_value=0,
        ),
        Column(
            name="tipo",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'cod_imovel' is always non-empty",
        "'status' is always AT, PE, SU, or CA",
        "'tipo' is always IRU, AST, or PCT",
        "'area_ha' is always >= 0",
        "'uf' is always a valid Brazilian state code",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("sicar_imoveis", SICAR_IMOVEIS_V1)
register_contract("cadastro_rural", SICAR_IMOVEIS_V1)

__all__ = [
    "AJUSTE_DIARIO_V1",
    "ANP_DIESEL_PRECOS_V1",
    "ANP_DIESEL_VENDAS_V1",
    "ANTT_PEDAGIO_FLUXO_V1",
    "ANTT_PEDAGIO_PRACAS_V1",
    "COMERCIO_BILATERAL_V1",
    "CONAB_PROGRESSO_V1",
    "PRECO_ATACADO_V1",
    "CREDITO_RURAL_V1_1",
    "DESMATAMENTO_DETER_V1",
    "DESMATAMENTO_PRODES_V1",
    "EXPORTACAO_V1",
    "FERTILIZANTE_V1",
    "FOCOS_QUEIMADAS_V1",
    "MAPA_PSR_APOLICES_V1",
    "MAPA_PSR_SINISTROS_V1",
    "MAPBIOMAS_COBERTURA_V1",
    "MAPBIOMAS_TRANSICAO_V1",
    "MOVIMENTACAO_PORTUARIA_V1",
    "POSICOES_ABERTAS_V1",
    "SICAR_IMOVEIS_V1",
    "TRADE_MIRROR_V1",
]
