"""
Final comprehensive tests to achieve 100% coverage
Covers all remaining uncovered lines
"""

from datetime import date

from catalogmx.catalogs.banxico import BankCatalog, CodigosPlazaCatalog, MonedasDivisas, UDICatalog
from catalogmx.catalogs.inegi import StateCatalog
from catalogmx.catalogs.mexico import (
    HoyNoCirculaCatalog,
    PlacasFormatosCatalog,
    SalariosMinimos,
    UMACatalog,
)
from catalogmx.catalogs.sat.carta_porte import (
    AeropuertosCatalog,
    CarreterasCatalog,
    ConfigAutotransporteCatalog,
    MaterialPeligrosoCatalog,
    PuertosMaritimos,
    TipoEmbalajeCatalog,
    TipoPermisoCatalog,
)
from catalogmx.catalogs.sat.comercio_exterior import (
    EstadoCatalog,
    IncotermsValidator,
    MonedaCatalog,
    PaisCatalog,
    RegistroIdentTribCatalog,
)
from catalogmx.catalogs.sat.nomina import (
    PeriodicidadPagoCatalog,
    RiesgoPuestoCatalog,
    TipoContratoCatalog,
    TipoNominaCatalog,
    TipoRegimenCatalog as NominaTipoRegimenCatalog,
)
from catalogmx.helpers import generate_curp, generate_rfc_persona_fisica, generate_rfc_persona_moral


class TestBankCatalogFinal:
    """Final tests for Bank Catalog"""

    def test_get_bank_by_name_with_accent(self):
        """Test getting bank by name with accents"""
        result = BankCatalog.get_bank_by_name("Banamex")
        assert result is None or isinstance(result, dict)

    def test_get_spei_banks(self):
        """Test getting SPEI banks"""
        result = BankCatalog.get_spei_banks()
        assert isinstance(result, list)


class TestCodigosPlazaFinal:
    """Final tests for Codigos Plaza"""

    def test_get_plazas_duplicadas(self):
        """Test getting duplicate plazas"""
        result = CodigosPlazaCatalog.get_plazas_duplicadas()
        assert isinstance(result, dict)


class TestMonedasDivisasFinal:
    """Final tests for Monedas Divisas"""

    def test_get_formato_moneda_with_zero_decimals(self):
        """Test get_formato_moneda with zero decimals currency"""
        # JPY has 0 decimals
        result = MonedasDivisas.get_formato_moneda("JPY")
        if result:
            assert "formato_ejemplo" in result


class TestUDICatalogFinal:
    """Final tests for UDI Catalog"""

    def test_get_por_fecha_fallback_to_mensual(self):
        """Test getting UDI with fallback to monthly average"""
        # Try a date that may not have daily data
        result = UDICatalog.get_por_fecha("2024-01-15")
        assert result is None or isinstance(result, dict)

    def test_get_por_fecha_invalid_format(self):
        """Test getting UDI with invalid date format"""
        result = UDICatalog.get_por_fecha("invalid")
        assert result is None

    def test_pesos_a_udis_with_data(self):
        """Test converting pesos to UDIs"""
        data = UDICatalog.get_data()
        if data:
            fecha = data[-1]["fecha"]
            result = UDICatalog.pesos_a_udis(10000, fecha)
            if result is not None:
                assert isinstance(result, float)

    def test_udis_a_pesos_with_data(self):
        """Test converting UDIs to pesos"""
        data = UDICatalog.get_data()
        if data:
            fecha = data[-1]["fecha"]
            result = UDICatalog.udis_a_pesos(100, fecha)
            if result is not None:
                assert isinstance(result, float)

    def test_calcular_variacion_with_data(self):
        """Test calculating variation"""
        data = UDICatalog.get_data()
        if len(data) >= 2:
            fecha_inicio = data[0]["fecha"]
            fecha_fin = data[1]["fecha"]
            result = UDICatalog.calcular_variacion(fecha_inicio, fecha_fin)
            if result is not None:
                assert isinstance(result, float)


class TestStateCatalogFinal:
    """Final tests for State Catalog"""

    def test_get_all_states(self):
        """Test getting all states"""
        result = StateCatalog.get_all_states()
        assert isinstance(result, list)


class TestHoyNoCirculaFinal:
    """Final tests for Hoy No Circula"""

    def test_puede_circular_edge_cases(self):
        """Test puede_circular with various edge cases"""
        # Test with different terminaciones
        for term in ["0", "5", "6", "7", "8", "9"]:
            result = HoyNoCirculaCatalog.puede_circular(term, "lunes", "2")
            assert isinstance(result, bool)

    def test_get_data(self):
        """Test getting data"""
        result = HoyNoCirculaCatalog.get_data()
        assert isinstance(result, dict)


class TestPlacasFormatosFinal:
    """Final tests for Placas Formatos"""

    def test_detect_formato_various(self):
        """Test detecting formato with various inputs"""
        test_placas = ["ABC-123-D", "1234-ABC", "INVALID"]
        for placa in test_placas:
            result = PlacasFormatosCatalog.detect_formato(placa)
            assert result is None or isinstance(result, dict)


class TestSalariosMinimosAndUMAFinal:
    """Final tests for Salarios and UMA"""

    def test_salarios_get_por_zona(self):
        """Test getting salarios by zona"""
        if hasattr(SalariosMinimos, "get_por_zona"):
            result = SalariosMinimos.get_por_zona("A")
            assert result is None or isinstance(result, list)

    def test_uma_get_valor_not_found(self):
        """Test getting UMA valor for old year"""
        result = UMACatalog.get_valor(2010)
        assert result is None or isinstance(result, (int, float))


class TestAeropuertosCarreterasPuertosFinal:
    """Final tests for Aeropuertos, Carreteras, Puertos"""

    def test_aeropuertos_get_by_state_not_found(self):
        """Test getting aeropuertos by nonexistent state"""
        result = AeropuertosCatalog.get_by_state("NonExistent")
        assert isinstance(result, list)

    def test_aeropuertos_search_by_name_not_found(self):
        """Test searching aeropuertos by nonexistent name"""
        result = AeropuertosCatalog.search_by_name("NonExistent12345")
        assert isinstance(result, list)

    def test_carreteras_get_all(self):
        """Test getting all carreteras"""
        result = CarreterasCatalog.get_all()
        assert isinstance(result, list)

    def test_carreteras_search_by_name_not_found(self):
        """Test searching carreteras by nonexistent name"""
        result = CarreterasCatalog.search_by_name("NonExistent12345")
        assert isinstance(result, list)

    def test_puertos_get_by_coast_not_found(self):
        """Test getting puertos by nonexistent coast"""
        result = PuertosMaritimos.get_by_coast("NonExistent")
        assert isinstance(result, list)

    def test_puertos_get_by_state_not_found(self):
        """Test getting puertos by nonexistent state"""
        result = PuertosMaritimos.get_by_state("NonExistent")
        assert isinstance(result, list)

    def test_puertos_search_by_name_not_found(self):
        """Test searching puertos by nonexistent name"""
        result = PuertosMaritimos.search_by_name("NonExistent12345")
        assert isinstance(result, list)


class TestConfigMaterialPermisoEmbalajeFinal:
    """Final tests for Config, Material, Permiso, Embalaje"""

    def test_config_get_by_type(self):
        """Test getting config by type"""
        all_configs = ConfigAutotransporteCatalog.get_all()
        if all_configs:
            tipo = all_configs[0].get("type", "")
            if tipo:
                result = ConfigAutotransporteCatalog.get_by_type(tipo)
                assert isinstance(result, list)

    def test_material_get_by_class(self):
        """Test getting material by class"""
        all_materiales = MaterialPeligrosoCatalog.get_all()
        if all_materiales:
            for material in all_materiales:
                if "class" in material:
                    result = MaterialPeligrosoCatalog.get_by_class(material["class"][:1])
                    assert isinstance(result, list)
                    break

    def test_material_get_by_packing_group(self):
        """Test getting material by packing group"""
        result = MaterialPeligrosoCatalog.get_by_packing_group("I")
        assert isinstance(result, list)

    def test_permiso_get_by_transport(self):
        """Test getting permiso by transport"""
        all_permisos = TipoPermisoCatalog.get_all()
        if all_permisos:
            for permiso in all_permisos:
                if "transport" in permiso or "transporte" in permiso:
                    transport = permiso.get("transport", permiso.get("transporte", ""))
                    if transport:
                        result = TipoPermisoCatalog.get_by_transport(transport)
                        assert isinstance(result, list)
                        break

    def test_embalaje_get_by_material(self):
        """Test getting embalaje by material"""
        all_embalajes = TipoEmbalajeCatalog.get_all()
        if all_embalajes:
            for embalaje in all_embalajes:
                if "material" in embalaje:
                    result = TipoEmbalajeCatalog.get_by_material(embalaje["material"])
                    assert isinstance(result, list)
                    break


class TestNominaFinal:
    """Final tests for Nomina catalogs"""

    def test_riesgo_get_by_level(self):
        """Test getting riesgo by level if method exists"""
        all_riesgos = RiesgoPuestoCatalog.get_all()
        if all_riesgos and hasattr(RiesgoPuestoCatalog, "get_by_level"):
            for riesgo in all_riesgos:
                if "level" in riesgo or "nivel" in riesgo:
                    level = riesgo.get("level", riesgo.get("nivel", ""))
                    if level:
                        result = RiesgoPuestoCatalog.get_by_level(str(level))
                        assert isinstance(result, list)
                        break

    def test_nomina_is_ordinaria(self):
        """Test checking if nomina is ordinaria"""
        all_tipos = TipoNominaCatalog.get_all()
        if all_tipos:
            result = TipoNominaCatalog.is_ordinaria(all_tipos[0]["code"])
            assert isinstance(result, bool)


class TestComercioExteriorFinal:
    """Final tests for Comercio Exterior"""

    def test_incoterms_search(self):
        """Test searching incoterms"""
        result = IncotermsValidator.search("Free")
        assert isinstance(result, list)

    def test_moneda_validate_conversion_usd_errors(self):
        """Test moneda conversion validation with errors"""
        # Missing fields should generate errors
        result = MonedaCatalog.validate_conversion_usd(
            {
                "moneda": "MXN",
                "total": 20000,
                # Missing tipo_cambio_usd and total_usd
            }
        )
        assert isinstance(result, dict)
        assert "errors" in result

    def test_pais_search(self):
        """Test searching paises"""
        result = PaisCatalog.search("Mexico")
        assert isinstance(result, list)

    def test_registro_validate_tax_id_with_format(self):
        """Test validating tax ID with format validation"""
        all_registros = RegistroIdentTribCatalog.get_all()
        if all_registros:
            for registro in all_registros:
                if "format_pattern" in registro:
                    result = RegistroIdentTribCatalog.validate_tax_id(
                        registro["code"], "123456789ABC"
                    )
                    assert isinstance(result, dict)
                    break


class TestHelpersFinal:
    """Final tests for helpers"""

    def test_generate_curp_with_date_object(self):
        """Test generating CURP with date object"""
        result = generate_curp(
            nombre="Juan",
            apellido_paterno="Garcia",
            apellido_materno="Lopez",
            fecha_nacimiento=date(1990, 5, 15),
            sexo="H",
            estado="Jalisco",
        )
        assert len(result) == 18

    def test_generate_rfc_persona_fisica_standard(self):
        """Test generating RFC fisica"""
        result = generate_rfc_persona_fisica(
            nombre="Juan",
            apellido_paterno="Garcia",
            apellido_materno="Lopez",
            fecha_nacimiento=date(1990, 5, 15),
        )
        assert len(result) == 13

    def test_generate_rfc_persona_moral_standard(self):
        """Test generating RFC moral"""
        result = generate_rfc_persona_moral(
            razon_social="Tecnologia Sistemas Integrales S.A.", fecha_constitucion=date(2009, 9, 9)
        )
        assert len(result) == 12
