from dataclasses import dataclass
from typing import Dict, Optional
from enum import Enum


class Bloco(Enum):
    A = "A"
    B = "B"
    C = "C"
    D = "D"
    E = "E"


class TipoAtuacao(Enum):
    FUNCAO = "Função"
    COMPETENCIA_RECONHECIMENTO = "Competência e Reconhecimento"
    PAPEL = "Papel"
    PARTICIPACAO = "Participação"


@dataclass(frozen=True)
class CriterioPontuacao:
    codigo: str
    bloco: Bloco
    tipo: TipoAtuacao
    base: int
    teto: int
    pontua_tempo: bool = False
    multiplicador_tempo: int = 0
    teto_tempo: int = 0
    bonus_atualidade: int = 0
    bonus_retorno: int = 0
    bonus_continuidade_8anos: int = 0
    bonus_recorrencia_anual: int = 0
    teto_recorrencia: int = 0
    bonus_recorrencia_participacao: int = 0
    teto_recorrencia_participacao: int = 0
    gera_selo: bool = False


CRITERIOS: Dict[str, CriterioPontuacao] = {
    "CA": CriterioPontuacao(
        codigo="CA",
        bloco=Bloco.A,
        tipo=TipoAtuacao.FUNCAO,
        base=200,
        teto=450,
        pontua_tempo=True,
        multiplicador_tempo=10,
        teto_tempo=100,
        bonus_atualidade=30,
        bonus_retorno=20,
    ),
    "CAJ": CriterioPontuacao(
        codigo="CAJ",
        bloco=Bloco.A,
        tipo=TipoAtuacao.FUNCAO,
        base=150,
        teto=370,
        pontua_tempo=True,
        multiplicador_tempo=8,
        teto_tempo=80,
        bonus_atualidade=20,
        bonus_retorno=15,
    ),
    "CAJ_MP": CriterioPontuacao(
        codigo="CAJ_MP",
        bloco=Bloco.A,
        tipo=TipoAtuacao.FUNCAO,
        base=120,
        teto=315,
        pontua_tempo=True,
        multiplicador_tempo=6,
        teto_tempo=60,
        bonus_atualidade=15,
        bonus_retorno=10,
    ),
    "CAM": CriterioPontuacao(
        codigo="CAM",
        bloco=Bloco.A,
        tipo=TipoAtuacao.FUNCAO,
        base=100,
        teto=280,
        pontua_tempo=True,
        multiplicador_tempo=5,
        teto_tempo=50,
        bonus_atualidade=20,
        bonus_retorno=10,
    ),
    "PPG_COORD": CriterioPontuacao(
        codigo="PPG_COORD",
        bloco=Bloco.E,
        tipo=TipoAtuacao.FUNCAO,
        base=0,
        teto=0,
        pontua_tempo=True,
        multiplicador_tempo=0,
        teto_tempo=0,
        bonus_atualidade=15,
        bonus_retorno=10,
        bonus_continuidade_8anos=15,
        gera_selo=True,
    ),
    "CONS_ATIVO": CriterioPontuacao(
        codigo="CONS_ATIVO",
        bloco=Bloco.B,
        tipo=TipoAtuacao.FUNCAO,
        base=150,
        teto=230,
        pontua_tempo=True,
        multiplicador_tempo=5,
        teto_tempo=50,
        bonus_atualidade=20,
        bonus_retorno=15,
        bonus_continuidade_8anos=20,
    ),
    "CONS_HIST": CriterioPontuacao(
        codigo="CONS_HIST",
        bloco=Bloco.B,
        tipo=TipoAtuacao.FUNCAO,
        base=100,
        teto=230,
        pontua_tempo=True,
        multiplicador_tempo=5,
        teto_tempo=50,
        bonus_retorno=20,
        bonus_continuidade_8anos=20,
    ),
    "CONS_FALECIDO": CriterioPontuacao(
        codigo="CONS_FALECIDO",
        bloco=Bloco.B,
        tipo=TipoAtuacao.FUNCAO,
        base=100,
        teto=230,
        pontua_tempo=True,
        multiplicador_tempo=5,
        teto_tempo=50,
        bonus_continuidade_8anos=20,
    ),
    "INSC_AUTOR": CriterioPontuacao(
        codigo="INSC_AUTOR",
        bloco=Bloco.C,
        tipo=TipoAtuacao.FUNCAO,
        base=10,
        teto=20,
        bonus_recorrencia_participacao=2,
        teto_recorrencia_participacao=10,
    ),
    "INSC_INST_AUTOR": CriterioPontuacao(
        codigo="INSC_INST_AUTOR",
        bloco=Bloco.C,
        tipo=TipoAtuacao.FUNCAO,
        base=20,
        teto=50,
        bonus_recorrencia_participacao=5,
        teto_recorrencia_participacao=10,
    ),
    "AVAL_COMIS_PREMIO": CriterioPontuacao(
        codigo="AVAL_COMIS_PREMIO",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PAPEL,
        base=30,
        teto=60,
        bonus_recorrencia_anual=2,
        teto_recorrencia=15,
    ),
    "AVAL_COMIS_GP": CriterioPontuacao(
        codigo="AVAL_COMIS_GP",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PAPEL,
        base=40,
        teto=80,
        bonus_recorrencia_anual=3,
        teto_recorrencia=20,
    ),
    "COORD_COMIS_PREMIO": CriterioPontuacao(
        codigo="COORD_COMIS_PREMIO",
        bloco=Bloco.C,
        tipo=TipoAtuacao.FUNCAO,
        base=40,
        teto=100,
        bonus_recorrencia_anual=4,
        teto_recorrencia=20,
    ),
    "COORD_COMIS_GP": CriterioPontuacao(
        codigo="COORD_COMIS_GP",
        bloco=Bloco.C,
        tipo=TipoAtuacao.FUNCAO,
        base=50,
        teto=120,
        bonus_recorrencia_anual=6,
        teto_recorrencia=20,
    ),
    "BOL_BPQ_NIVEL": CriterioPontuacao(
        codigo="BOL_BPQ_NIVEL",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=30,
        teto=60,
        gera_selo=True,
    ),
    "PREMIACAO_GP_AUTOR": CriterioPontuacao(
        codigo="PREMIACAO_GP_AUTOR",
        bloco=Bloco.C,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=100,
        teto=300,
        gera_selo=True,
    ),
    "PREMIACAO_AUTOR": CriterioPontuacao(
        codigo="PREMIACAO_AUTOR",
        bloco=Bloco.C,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=50,
        teto=150,
        gera_selo=True,
    ),
    "MENCAO_AUTOR": CriterioPontuacao(
        codigo="MENCAO_AUTOR",
        bloco=Bloco.C,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=30,
        teto=90,
        gera_selo=True,
    ),
    "EVENTO": CriterioPontuacao(
        codigo="EVENTO",
        bloco=Bloco.D,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=1,
        teto=5,
        bonus_recorrencia_participacao=1,
        teto_recorrencia_participacao=10,
    ),
    "PROJ": CriterioPontuacao(
        codigo="PROJ",
        bloco=Bloco.D,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=10,
        teto=30,
        bonus_recorrencia_participacao=2,
        teto_recorrencia_participacao=10,
    ),
    "IDIOMA_BILINGUE": CriterioPontuacao(
        codigo="IDIOMA_BILINGUE",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "IDIOMA_MULTILINGUE": CriterioPontuacao(
        codigo="IDIOMA_MULTILINGUE",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "TITULACAO_MESTRE": CriterioPontuacao(
        codigo="TITULACAO_MESTRE",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "TITULACAO_DOUTOR": CriterioPontuacao(
        codigo="TITULACAO_DOUTOR",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "TITULACAO_POS_DOUTOR": CriterioPontuacao(
        codigo="TITULACAO_POS_DOUTOR",
        bloco=Bloco.D,
        tipo=TipoAtuacao.COMPETENCIA_RECONHECIMENTO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_POS_DOC": CriterioPontuacao(
        codigo="ORIENT_POS_DOC",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_POS_DOC_PREM": CriterioPontuacao(
        codigo="ORIENT_POS_DOC_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_TESE": CriterioPontuacao(
        codigo="ORIENT_TESE",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_TESE_PREM": CriterioPontuacao(
        codigo="ORIENT_TESE_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_DISS": CriterioPontuacao(
        codigo="ORIENT_DISS",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "ORIENT_DISS_PREM": CriterioPontuacao(
        codigo="ORIENT_DISS_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_POS_DOC": CriterioPontuacao(
        codigo="CO_ORIENT_POS_DOC",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_POS_DOC_PREM": CriterioPontuacao(
        codigo="CO_ORIENT_POS_DOC_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_TESE": CriterioPontuacao(
        codigo="CO_ORIENT_TESE",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_TESE_PREM": CriterioPontuacao(
        codigo="CO_ORIENT_TESE_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_DISS": CriterioPontuacao(
        codigo="CO_ORIENT_DISS",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "CO_ORIENT_DISS_PREM": CriterioPontuacao(
        codigo="CO_ORIENT_DISS_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_POS_DOC": CriterioPontuacao(
        codigo="MB_BANCA_POS_DOC",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_POS_DOC_PREM": CriterioPontuacao(
        codigo="MB_BANCA_POS_DOC_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_TESE": CriterioPontuacao(
        codigo="MB_BANCA_TESE",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_TESE_PREM": CriterioPontuacao(
        codigo="MB_BANCA_TESE_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_DISS": CriterioPontuacao(
        codigo="MB_BANCA_DISS",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
    "MB_BANCA_DISS_PREM": CriterioPontuacao(
        codigo="MB_BANCA_DISS_PREM",
        bloco=Bloco.C,
        tipo=TipoAtuacao.PARTICIPACAO,
        base=0,
        teto=0,
        gera_selo=True,
    ),
}


def get_criterio(codigo: str) -> Optional[CriterioPontuacao]:
    return CRITERIOS.get(codigo)


def get_criterios_bloco(bloco: Bloco) -> Dict[str, CriterioPontuacao]:
    return {k: v for k, v in CRITERIOS.items() if v.bloco == bloco}
