from __future__ import annotations

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

IBGE_PAM_V1 = Contract(
    name="ibge.pam",
    version="1.0",
    effective_from="0.3.0",
    primary_key=["ano", "produto", "localidade"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1974,
        ),
        Column(
            name="localidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="area_plantada",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="area_colhida",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="producao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="ton",
            stable=True,
            min_value=0,
        ),
        Column(
            name="rendimento",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg/ha",
            stable=True,
            min_value=0,
        ),
        Column(
            name="valor_producao",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="mil_reais",
            stable=True,
            min_value=0,
        ),
        Column(
            name="fonte",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always a valid year (>= 1974)",
        "Numeric values are always >= 0",
        "'fonte' is always 'ibge_pam'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

IBGE_LSPA_V1 = Contract(
    name="ibge.lspa",
    version="1.0",
    effective_from="0.3.0",
    primary_key=["ano", "mes", "produto"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1974,
        ),
        Column(
            name="mes",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
            min_value=1,
            max_value=12,
        ),
        Column(
            name="produto",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="variavel",
            type=ColumnType.STRING,
            nullable=True,
            stable=False,
        ),
        Column(
            name="valor",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=False,
        ),
        Column(
            name="fonte",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always a valid year",
        "'mes' is between 1 and 12 when present",
        "'fonte' is always 'ibge_lspa'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

IBGE_PPM_V1 = Contract(
    name="ibge.ppm",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["ano", "especie", "localidade"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=1974,
        ),
        Column(
            name="localidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="localidade_cod",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
        ),
        Column(
            name="especie",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="valor",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="unidade",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="fonte",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always a valid year (>= 1974)",
        "Numeric values are always >= 0",
        "'fonte' is always 'ibge_ppm'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

IBGE_ABATE_V1 = Contract(
    name="ibge.abate",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["trimestre", "especie", "localidade"],
    columns=[
        Column(
            name="trimestre",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="localidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="localidade_cod",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
        ),
        Column(
            name="especie",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="animais_abatidos",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="cabeças",
            stable=True,
            min_value=0,
        ),
        Column(
            name="peso_carcacas",
            type=ColumnType.FLOAT,
            nullable=True,
            unit="kg",
            stable=True,
            min_value=0,
        ),
        Column(
            name="fonte",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'trimestre' format is YYYYQQ (e.g. 202303)",
        "Numeric values are always >= 0",
        "'fonte' is always 'ibge_abate'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

IBGE_CENSO_AGRO_V1 = Contract(
    name="ibge.censo_agro",
    version="1.0",
    effective_from="0.10.0",
    primary_key=["ano", "tema", "categoria", "variavel", "localidade"],
    columns=[
        Column(
            name="ano",
            type=ColumnType.INTEGER,
            nullable=False,
            stable=True,
            min_value=2006,
        ),
        Column(
            name="localidade",
            type=ColumnType.STRING,
            nullable=True,
            stable=True,
        ),
        Column(
            name="localidade_cod",
            type=ColumnType.INTEGER,
            nullable=True,
            stable=True,
        ),
        Column(
            name="tema",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="categoria",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="variavel",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="valor",
            type=ColumnType.FLOAT,
            nullable=True,
            stable=True,
            min_value=0,
        ),
        Column(
            name="unidade",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
        Column(
            name="fonte",
            type=ColumnType.STRING,
            nullable=False,
            stable=True,
        ),
    ],
    guarantees=[
        "Column names never change (additions only)",
        "'ano' is always a valid census year (>= 2006)",
        "Numeric values are always >= 0",
        "'fonte' is always 'ibge_censo_agro'",
    ],
    breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
)

register_contract("producao_anual", IBGE_PAM_V1)
register_contract("pecuaria_municipal", IBGE_PPM_V1)
register_contract("abate_trimestral", IBGE_ABATE_V1)
register_contract("censo_agropecuario", IBGE_CENSO_AGRO_V1)

__all__ = [
    "IBGE_ABATE_V1",
    "IBGE_CENSO_AGRO_V1",
    "IBGE_LSPA_V1",
    "IBGE_PAM_V1",
    "IBGE_PPM_V1",
]
