from .type_parser import flatten_glue_type


def test_flatten_glue_type_struct():
    field_type = (
        "struct<activity_zone:struct<location:struct<address:string,city:string>,"
        "radius:bigint>,radius:int,location:struct<address:string>>"
    )

    flattened = flatten_glue_type("activity", field_type)
    assert flattened == [
        ("activity", "struct", True),
        ("activity.activity_zone", "struct", False),
        ("activity.activity_zone.location", "struct", False),
        ("activity.activity_zone.location.address", "string", False),
        ("activity.activity_zone.location.city", "string", False),
        ("activity.activity_zone.radius", "bigint", False),
        ("activity.radius", "int", False),
        ("activity.location", "struct", False),
        ("activity.location.address", "string", False),
    ]


def test_flatten_glue_type_array_map():
    field_type = "array<map<string,struct<score:double>>>"
    flattened = flatten_glue_type("metrics", field_type)
    assert flattened == [
        ("metrics", "array", True),
    ]


def test_flatten_glue_type_array_of_primitive():
    field_type = "array<string>"
    flattened = flatten_glue_type("tags", field_type)
    assert flattened == [
        ("tags", "array", True),
    ]


def test_flatten_glue_type_array_of_array():
    field_type = "array<array<int>>"
    flattened = flatten_glue_type("matrix", field_type)
    assert flattened == [
        ("matrix", "array", True),
    ]


def test_flatten_glue_type_map():
    field_type = "map<string,struct<score:double>>"
    flattened = flatten_glue_type("labels", field_type)
    assert flattened == [
        ("labels", "map", True),
    ]


def test_flatten_glue_type_array_of_struct():
    field_type = "array<struct<id:string,type:string,price:bigint,payer:string,payee:string>>"
    flattened = flatten_glue_type("payments", field_type)
    assert flattened == [
        ("payments", "array", True),
        ("payments.id", "string", False),
        ("payments.type", "string", False),
        ("payments.price", "bigint", False),
        ("payments.payer", "string", False),
        ("payments.payee", "string", False),
    ]


def test_flatten_glue_type_simple_struct():
    field_type = "struct<ad_id:bigint,list_id:bigint,category:int>"
    flattened = flatten_glue_type("ad", field_type)
    assert flattened == [
        ("ad", "struct", True),
        ("ad.ad_id", "bigint", False),
        ("ad.list_id", "bigint", False),
        ("ad.category", "int", False),
    ]


def test_flatten_glue_type_struct_with_array_and_map():
    field_type = (
        "struct<price_cents:bigint,stock_quantity:bigint,reference:string,"
        "images:array<string>,ad_params:map<string,string>,"
        "max_stock_quantity:bigint>"
    )
    flattened = flatten_glue_type("inventory", field_type)
    assert flattened == [
        ("inventory", "struct", True),
        ("inventory.price_cents", "bigint", False),
        ("inventory.stock_quantity", "bigint", False),
        ("inventory.reference", "string", False),
        ("inventory.images", "array", False),
        ("inventory.ad_params", "map", False),
        ("inventory.max_stock_quantity", "bigint", False),
    ]


def test_flatten_glue_type_array_of_struct_with_nested_map():
    field_type = (
        "array<struct<description:string,item_type:map<string,string>,"
        "price:int,price_no_tax:int,tax_rate:float,metadata:string,"
        "target_user:string,target_entity:string,item_id:string,"
        "category_id:string,sub_category_id:string,technical_name:string>>"
    )
    flattened = flatten_glue_type("items", field_type)
    assert flattened == [
        ("items", "array", True),
        ("items.description", "string", False),
        ("items.item_type", "map", False),
        ("items.price", "int", False),
        ("items.price_no_tax", "int", False),
        ("items.tax_rate", "float", False),
        ("items.metadata", "string", False),
        ("items.target_user", "string", False),
        ("items.target_entity", "string", False),
        ("items.item_id", "string", False),
        ("items.category_id", "string", False),
        ("items.sub_category_id", "string", False),
        ("items.technical_name", "string", False),
    ]


def test_flatten_glue_type_array_of_struct_with_booleans():
    field_type = (
        "array<struct<type:string,paid:int,revenue:int,status:string,"
        "reference:string,metadata:string,updated:string,payment_id:string,"
        "with_saving_card:boolean,use_saved_card:boolean,"
        "device_fingerprint:string,user_agent:string,active:boolean>>"
    )
    flattened = flatten_glue_type("transactions", field_type)
    assert flattened == [
        ("transactions", "array", True),
        ("transactions.type", "string", False),
        ("transactions.paid", "int", False),
        ("transactions.revenue", "int", False),
        ("transactions.status", "string", False),
        ("transactions.reference", "string", False),
        ("transactions.metadata", "string", False),
        ("transactions.updated", "string", False),
        ("transactions.payment_id", "string", False),
        ("transactions.with_saving_card", "boolean", False),
        ("transactions.use_saved_card", "boolean", False),
        ("transactions.device_fingerprint", "string", False),
        ("transactions.user_agent", "string", False),
        ("transactions.active", "boolean", False),
    ]


def test_flatten_glue_type_parameterized_primitives():
    field_type = "struct<p:decimal(10,2),v:varchar(255),c:char(3)>"
    flattened = flatten_glue_type("metrics", field_type)
    assert flattened == [
        ("metrics", "struct", True),
        ("metrics.p", "decimal", False),
        ("metrics.v", "varchar", False),
        ("metrics.c", "char", False),
    ]
