from typing import Dict, Union

from graphql import (
    GraphQLBoolean,
    GraphQLFloat,
    GraphQLInputField,
    GraphQLInt,
    GraphQLList,
    GraphQLNonNull,
    GraphQLScalarType,
    GraphQLString,
)
from sqlalchemy import ARRAY, Boolean, Float, Integer
from sqlalchemy.dialects.postgresql import ARRAY as PGARRAY
from sqlalchemy.types import TypeEngine


def get_graphql_type_from_column(column_type: TypeEngine) -> Union[GraphQLScalarType, GraphQLList]:
    if isinstance(column_type, Integer):
        return GraphQLInt

    if isinstance(column_type, Float):
        return GraphQLFloat

    if isinstance(column_type, Boolean):
        return GraphQLBoolean

    if isinstance(column_type, (ARRAY, PGARRAY)):
        return GraphQLList(get_graphql_type_from_column(column_type.item_type))

    return GraphQLString


def get_base_comparison_fields(graphql_type: Union[GraphQLScalarType, GraphQLList]) -> Dict[str, GraphQLInputField]:
    return {
        "_eq": GraphQLInputField(graphql_type),
        "_neq": GraphQLInputField(graphql_type),
        "_in": GraphQLInputField(GraphQLList(GraphQLNonNull(graphql_type))),
        "_nin": GraphQLInputField(GraphQLList(GraphQLNonNull(graphql_type))),
        "_lt": GraphQLInputField(graphql_type),
        "_gt": GraphQLInputField(graphql_type),
        "_gte": GraphQLInputField(graphql_type),
        "_lte": GraphQLInputField(graphql_type),
        "_is_null": GraphQLInputField(GraphQLBoolean),
    }


def get_string_comparison_fields() -> Dict[str, GraphQLInputField]:
    return {"_like": GraphQLInputField(GraphQLString), "_nlike": GraphQLInputField(GraphQLString)}

[(36, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (37, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (40, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (41, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (42, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (43, 'graphql.GraphQLInputField', 'GraphQLInputField', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (44, 'graphql.GraphQLInputField', 'GraphQLInputField', (['GraphQLBoolean'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (49, 'graphql.GraphQLInputField', 'GraphQLInputField', (['GraphQLString'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (49, 'graphql.GraphQLInputField', 'GraphQLInputField', (['GraphQLString'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (38, 'graphql.GraphQLNonNull', 'GraphQLNonNull', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n'), (39, 'graphql.GraphQLNonNull', 'GraphQLNonNull', (['graphql_type'], {}), False, 'from graphql import GraphQLBoolean, GraphQLFloat, GraphQLInputField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLScalarType, GraphQLString\n')]