"""
pyjuris.pandas_utils — integração com pandas

Requer: pip install pyjuris[pandas]

Funções principais:
    normalizar_dataframe(df, input_template, output_template) -> DataFrame
    fenomenos_para_dataframe(resultados)                      -> DataFrame
    to_instancias_dataframe(resultados)                       -> DataFrame
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pandas as pd


def _check_pandas() -> None:
    try:
        import pandas  # noqa: F401
    except ImportError:
        raise ImportError(
            "pandas é necessário para usar pyjuris.pandas_utils.\n"
            "Instale com: pip install pyjuris[pandas]"
        )


def normalizar_dataframe(
    df: "pd.DataFrame",
    coluna_payload: str = "payload",
    input_template: str = "escavador",
    output_template: str = "lops_api",
    enrich_orgaos: bool = True,
    coluna_resultado: str = "pyjuris",
    erros: str = "coerce",
) -> "pd.DataFrame":
    """
    Normaliza uma coluna de payloads JSON em um DataFrame.

    Parâmetros
    ----------
    df : DataFrame com uma coluna de dicts (payloads brutos)
    coluna_payload : nome da coluna que contém os payloads (default: "payload")
    input_template : "escavador" | "datajud"
    output_template : "lops_api" | "datajud"
    enrich_orgaos : enriquecer com orgao_julgador_info (default: True)
    coluna_resultado : nome da coluna de saída (default: "pyjuris")
    erros : "coerce" → None em caso de erro | "raise" → propaga exceção

    Retorna
    -------
    DataFrame original com coluna adicional `coluna_resultado` contendo o
    resultado normalizado (dict) por linha.

    Exemplos
    --------
    >>> df = pd.DataFrame({"payload": [payload1, payload2]})
    >>> df = normalizar_dataframe(df)
    >>> df["pyjuris"].apply(lambda r: r["numero_cnj"])

    >>> # Expandir campos direto no DataFrame:
    >>> resultado = normalizar_dataframe(df)
    >>> expandido = expandir_campos(resultado["pyjuris"].tolist())
    """
    _check_pandas()
    import pandas as pd
    from pyjuris.pipeline import normalizar_processo

    def _processar(payload):
        if payload is None:
            return None
        try:
            return normalizar_processo(
                payload,
                input_template=input_template,
                output_template=output_template,
                enrich_orgaos=enrich_orgaos,
            )
        except Exception:
            if erros == "raise":
                raise
            return None

    resultado = df.copy()
    resultado[coluna_resultado] = resultado[coluna_payload].apply(_processar)
    return resultado


def expandir_campos(
    resultados: list[dict],
    campos: list[str] | None = None,
) -> "pd.DataFrame":
    """
    Expande uma lista de resultados normalizados em um DataFrame tabular.

    Extrai campos de topo do canonical (não expande instâncias).
    Útil para análise agregada, exportação para Excel, etc.

    Parâmetros
    ----------
    resultados : lista de dicts retornados por normalizar_processo()
    campos : lista de campos a extrair. Se None, extrai os principais.

    Exemplos
    --------
    >>> resultados = [normalizar_processo(p) for p in payloads]
    >>> df = expandir_campos(resultados)
    >>> df.to_excel("processos.xlsx", index=False)
    """
    _check_pandas()
    import pandas as pd

    _CAMPOS_PADRAO = [
        "numero_cnj",
        "tipo_principal",
        "fase_atual",
        "status_geral",
        "total_instancias",
        "segredo_justica",
        "nivel_sigilo",
        "capa_disponivel",
        "polo_ativo",
        "polo_passivo",
        "ano_inicio",
        "data_inicio",
        "data_ultima_movimentacao",
        "fenomenos_detectados",
    ]

    campos_usar = campos or _CAMPOS_PADRAO
    rows = []
    for r in resultados:
        if r is None:
            rows.append({c: None for c in campos_usar})
            continue
        row = {c: r.get(c) for c in campos_usar}
        # fenomenos_detectados como string separada por vírgula (amigável p/ Excel)
        if "fenomenos_detectados" in row and isinstance(row["fenomenos_detectados"], list):
            row["fenomenos_detectados"] = ", ".join(row["fenomenos_detectados"])
        rows.append(row)

    return pd.DataFrame(rows, columns=campos_usar)


def to_instancias_dataframe(resultados: list[dict]) -> "pd.DataFrame":
    """
    Expande instâncias de múltiplos processos em um DataFrame linha-por-instância.

    Cada linha representa uma instância judicial.
    Campos de topo (numero_cnj, polo_ativo, etc.) são replicados em cada linha.

    Útil para análise por grau, por tribunal, por órgão julgador.

    Exemplos
    --------
    >>> resultados = [normalizar_processo(p) for p in payloads]
    >>> df = to_instancias_dataframe(resultados)
    >>> df.groupby("tribunal_sigla")["classe"].value_counts()
    """
    _check_pandas()
    import pandas as pd

    rows = []
    for r in resultados:
        if not r:
            continue
        base = {
            "numero_cnj":              r.get("numero_cnj"),
            "tipo_principal":          r.get("tipo_principal"),
            "fase_atual":              r.get("fase_atual"),
            "status_geral":            r.get("status_geral"),
            "polo_ativo":              r.get("polo_ativo"),
            "polo_passivo":            r.get("polo_passivo"),
            "segredo_justica":         r.get("segredo_justica"),
            "nivel_sigilo":            r.get("nivel_sigilo"),
            "data_inicio":             r.get("data_inicio"),
            "data_ultima_movimentacao": r.get("data_ultima_movimentacao"),
        }
        for inst in r.get("instancias") or []:
            row = dict(base)
            row.update({
                "grau":                inst.get("grau"),
                "grau_formatado":      inst.get("grau_formatado"),
                "tribunal_sigla":      (inst.get("tribunal") or {}).get("sigla"),
                "tribunal_sistema":    (inst.get("tribunal") or {}).get("sistema"),
                "classe":              inst.get("classe"),
                "classe_codigo":       inst.get("classe_codigo"),
                "assunto_principal":   inst.get("assunto_principal"),
                "orgao_julgador":      inst.get("orgao_julgador"),
                "valor_causa":         inst.get("valor_causa"),
                "status_instancia":    inst.get("status"),
                "arquivado":           inst.get("arquivado"),
            })
            rows.append(row)

    return pd.DataFrame(rows)


def fenomenos_dataframe(resultados: list[dict]) -> "pd.DataFrame":
    """
    Gera um DataFrame com frequência de fenômenos detectados.

    Útil para análise de qualidade de dados em lote.

    Exemplos
    --------
    >>> df = fenomenos_dataframe(resultados)
    >>> df.sort_values("count", ascending=False)
    """
    _check_pandas()
    import pandas as pd
    from collections import Counter

    counter: Counter = Counter()
    for r in resultados:
        if r:
            counter.update(r.get("fenomenos_detectados") or [])

    return pd.DataFrame(
        [{"fenomeno": k, "count": v} for k, v in counter.most_common()],
        columns=["fenomeno", "count"],
    )
