import dynamix_sdk.types as sdk_types
from dynamix_sdk.utils import gen_cls_name_from_url_path


def test_api_class_naming(api_groups):
    for api_group in api_groups:
        correct_class_name = gen_cls_name_from_url_path(
            url_path=api_group.name,
            postfix='API',
        )
        assert api_group.cls.__qualname__ == correct_class_name, (
            f'\nAPI group: {api_group.name}'
            f'\nCorrect API class name: {correct_class_name}'
        )

        for api_subgroup in api_group.subgroups:
            correct_class_name = gen_cls_name_from_url_path(
                url_path=f'{api_group.name}/{api_subgroup.name}',
                postfix='API',
            )
            assert api_subgroup.cls.__qualname__ == correct_class_name, (
                f'\nAPI group: {api_group.name}'
                f'\nAPI subgroup: {api_subgroup.name}'
                f'\nCorrect API class name: {correct_class_name}'
            )


def test_protocol_class_naming(sdk_dx_functions):
    for sdk_func in sdk_dx_functions:
        correct_class_name = gen_cls_name_from_url_path(
            url_path=sdk_func.url_path,
            postfix='Protocol',
        )

        assert sdk_func.proto_cls.__qualname__ == correct_class_name, (
            f'\nFunction call attributes: {sdk_func.call_attrs}'
            f'\nURL path: {sdk_func.url_path}'
            f'\nCorrect Protocol class name: {correct_class_name}'
        )


def get_subclasses(cls: type, result: list[type] | None = None):
    if result:
        _result = result
    else:
        _result: list[type] = []

    for subclass in cls.__subclasses__():
        if issubclass(subclass.__bases__[0], cls):
            _result.append(subclass)
        _result += get_subclasses(subclass)

    return _result


def test_params_nested_model_class_naming():
    base_cls = sdk_types.BaseAPIParamsNestedModel
    for params_nm_cls in get_subclasses(base_cls):
        suffix = 'APIParamsNM'
        assert params_nm_cls.__qualname__.endswith(suffix), (
            f'Class {params_nm_cls.__qualname__}:'
            f' all subclasses of {base_cls.__qualname__}'
            f' must have a name with suffix "{suffix}".'
        )


def test_result_class_naming(sdk_dx_functions):
    for sdk_func in sdk_dx_functions:
        if issubclass(sdk_func.result_cls, sdk_types.BaseAPIResultModel):
            result_cls_postfix = 'ResultModel'
        elif issubclass(sdk_func.result_cls, sdk_types.BaseAPIResultStr):
            result_cls_postfix = 'ResultStr'
        elif issubclass(sdk_func.result_cls, sdk_types.BaseAPIResultInt):
            result_cls_postfix = 'ResultInt'
        elif issubclass(sdk_func.result_cls, sdk_types.BaseAPIResultBool):
            result_cls_postfix = 'ResultBool'
        else:
            raise TypeError

        result_cls_name = gen_cls_name_from_url_path(
            url_path=sdk_func.url_path,
            postfix=result_cls_postfix,
        )
        assert sdk_func.result_cls.__qualname__ == result_cls_name, (
            f'\nFunction call attributes: {sdk_func.call_attrs}'
            f'\nURL path: {sdk_func.url_path}'
            f'\nResult base class:'
            f' {sdk_func.result_cls.__bases__[0].__qualname__}'
            f'\nCorrect result class name: {result_cls_name}'
        )


def test_result_nested_model_class_naming():
    base_cls = sdk_types.BaseAPIResultNestedModel
    for result_nm_cls in get_subclasses(base_cls):
        suffix = 'APIResultNM'
        assert result_nm_cls.__qualname__.endswith(suffix), (
            f'Class {result_nm_cls.__qualname__}:'
            f' all subclasses of {base_cls.__qualname__}'
            f' must have a name with suffix "{suffix}".'
        )
