from __future__ import annotations

from dataclasses import dataclass
from enum import StrEnum

from .ic_tags import RCTTag


class RCTOperation(StrEnum):
    CANCELA_VAS = "cancela_vas"
    SGR_CODBAR = "sgr_codbar"
    CONTESTACAO = "contestacao"
    DEF_VALOR_AJUSTE = "def_valor_ajuste"
    REG_ATEND_VAS_AVULSO = "reg_atend_vas_avulso"
    REG_ATEND_VAS_ESTRAT = "reg_atend_vas_estrat"
    PDF_FATURA = "pdf_fatura"
    BASE_CONHECIMENTO = "base_conhecimento"
    REG_CHAMADO_BO_RT15 = "reg_chamado_bo_rt15"


@dataclass(frozen=True, slots=True)
class RCTPolicy:
    success: tuple[str, ...] = ()
    failure: tuple[str, ...] = ()


def _codes(*values) -> tuple[str, ...]:
    return tuple(str(getattr(v, "value", v)) for v in values)


RCT_POLICIES: dict[RCTOperation, RCTPolicy] = {
    RCTOperation.CANCELA_VAS: RCTPolicy(
        success=_codes(RCTTag.CANCELA_VAS_OK, RCTTag.CANCELA_VAS_2X_OK, RCTTag.CANCELA_VAS_3X_OK),
        failure=_codes(RCTTag.CANCELA_VAS_FAIL, RCTTag.CANCELA_VAS_2X_FAIL, RCTTag.CANCELA_VAS_3X_FAIL),
    ),
    RCTOperation.SGR_CODBAR: RCTPolicy(
        success=_codes(RCTTag.SGR_CODBAR_OK, RCTTag.SGR_CODBAR_2X_OK, RCTTag.SGR_CODBAR_3X_OK),
        failure=_codes(RCTTag.SGR_CODBAR_FAIL, RCTTag.SGR_CODBAR_2X_FAIL, RCTTag.SGR_CODBAR_3X_FAIL),
    ),
    RCTOperation.CONTESTACAO: RCTPolicy(
        success=_codes(RCTTag.CONTESTACAO_OK, RCTTag.CONTESTACAO_2X_OK, RCTTag.CONTESTACAO_3X_OK),
        failure=_codes(RCTTag.CONTESTACAO_FAIL, RCTTag.CONTESTACAO_2X_FAIL, RCTTag.CONTESTACAO_3X_FAIL),
    ),
    RCTOperation.DEF_VALOR_AJUSTE: RCTPolicy(
        success=_codes(RCTTag.DEF_VALOR_AJUSTE_OK, RCTTag.DEF_VALOR_AJUSTE_2X_OK, RCTTag.DEF_VALOR_AJUSTE_3X_OK),
        failure=_codes(RCTTag.DEF_VALOR_AJUSTE_FAIL, RCTTag.DEF_VALOR_AJUSTE_2X_FAIL, RCTTag.DEF_VALOR_AJUSTE_3X_FAIL),
    ),
    RCTOperation.REG_ATEND_VAS_AVULSO: RCTPolicy(
        success=_codes(RCTTag.REG_ATEND_VAS_AVULSO_OK, RCTTag.REG_ATEND_VAS_AVULSO_2X_OK, RCTTag.REG_ATEND_VAS_AVULSO_3X_OK),
        failure=_codes(RCTTag.REG_ATEND_VAS_AVULSO_FAIL, RCTTag.REG_ATEND_VAS_AVULSO_2X_FAIL, RCTTag.REG_ATEND_VAS_AVULSO_3X_FAIL),
    ),
    RCTOperation.REG_ATEND_VAS_ESTRAT: RCTPolicy(
        success=_codes(RCTTag.REG_ATEND_VAS_ESTRAT_OK, RCTTag.REG_ATEND_VAS_ESTRAT_2X_OK, RCTTag.REG_ATEND_VAS_ESTRAT_3X_OK),
        failure=_codes(RCTTag.REG_ATEND_VAS_ESTRAT_FAIL, RCTTag.REG_ATEND_VAS_ESTRAT_2X_FAIL, RCTTag.REG_ATEND_VAS_ESTRAT_3X_FAIL),
    ),
    RCTOperation.PDF_FATURA: RCTPolicy(
        success=_codes(RCTTag.PDF_FATURA_OK, RCTTag.PDF_FATURA_2X_OK, RCTTag.PDF_FATURA_3X_OK),
        failure=_codes(RCTTag.PDF_FATURA_FAIL, RCTTag.PDF_FATURA_2X_FAIL, RCTTag.PDF_FATURA_3X_FAIL),
    ),
    RCTOperation.BASE_CONHECIMENTO: RCTPolicy(
        success=_codes(RCTTag.BASE_CONHECIMENTO_OK, RCTTag.BASE_CONHECIMENTO_2X_OK, RCTTag.BASE_CONHECIMENTO_3X_OK),
        failure=_codes(RCTTag.BASE_CONHECIMENTO_FAIL, RCTTag.BASE_CONHECIMENTO_2X_FAIL, RCTTag.BASE_CONHECIMENTO_3X_FAIL),
    ),
    RCTOperation.REG_CHAMADO_BO_RT15: RCTPolicy(
        success=_codes(RCTTag.REG_CHAMADO_BO_RT15_OK, RCTTag.REG_CHAMADO_BO_RT15_2X_OK, RCTTag.REG_CHAMADO_BO_RT15_3X_OK),
        failure=_codes(RCTTag.REG_CHAMADO_BO_RT15_FAIL, RCTTag.REG_CHAMADO_BO_RT15_2X_FAIL, RCTTag.REG_CHAMADO_BO_RT15_3X_FAIL),
    ),
}


def rct_tags_for_attempt(operation: RCTOperation | str | None, attempt: int, *, success: bool) -> tuple[str, ...]:
    if operation is None or attempt < 1:
        return ()
    try:
        op = operation if isinstance(operation, RCTOperation) else RCTOperation(str(operation))
    except ValueError:
        return ()
    policy = RCT_POLICIES.get(op, RCTPolicy())
    group = policy.success if success else policy.failure
    idx = attempt - 1
    return (group[idx],) if idx < len(group) and group[idx] else ()
