import json

from shopify.metafield_values import (
    choices_from_metafield_definition,
    serialize_shopify_metafield_value,
)
from shopify.product_sync import map_payload_to_product_set_input


def test_serialize_shopify_boolean_values():
    assert serialize_shopify_metafield_value(True, "boolean") == "true"
    assert serialize_shopify_metafield_value(False, "boolean") == "false"
    assert serialize_shopify_metafield_value("1", "boolean") == "true"
    assert serialize_shopify_metafield_value("0", "boolean") == "false"
    assert serialize_shopify_metafield_value("yes", "boolean") == "true"
    assert serialize_shopify_metafield_value("N/A", "boolean") is None


def test_serialize_shopify_integer_values():
    assert serialize_shopify_metafield_value(12, "number_integer") == "12"
    assert serialize_shopify_metafield_value(12.0, "number_integer") == "12"
    assert serialize_shopify_metafield_value("24", "number_integer") == "24"
    assert serialize_shopify_metafield_value("12.5", "number_integer") is None
    assert serialize_shopify_metafield_value("", "number_integer") is None


def test_serialize_shopify_json_plain_text_wraps_object():
    assert serialize_shopify_metafield_value("Base Cabinets", "json") == '{"value": "Base Cabinets"}'
    assert serialize_shopify_metafield_value('{"a": 1}', "json") == '{"a": 1}'


def test_serialize_shopify_list_values():
    assert serialize_shopify_metafield_value("Hardware", "list.single_line_text_field") == '["Hardware"]'
    assert serialize_shopify_metafield_value("a, b", "list.single_line_text_field") == '["a", "b"]'
    assert serialize_shopify_metafield_value(["x", "y"], "list.single_line_text_field") == '["x", "y"]'


def test_serialize_shopify_list_values_with_choices():
    choices = ["Anna", "BILLY", "Home Surplus"]
    assert (
        serialize_shopify_metafield_value("home surplus", "list.single_line_text_field", choices=choices)
        == '["Home Surplus"]'
    )
    assert serialize_shopify_metafield_value("Unknown Brand", "list.single_line_text_field", choices=choices) is None


def test_serialize_shopify_metaobject_reference():
    assert (
        serialize_shopify_metafield_value(
            "gid://shopify/Metaobject/123",
            "metaobject_reference",
        )
        == "gid://shopify/Metaobject/123"
    )
    assert serialize_shopify_metafield_value("Anna", "metaobject_reference") is None


def test_choices_from_metafield_definition():
    raw = {
        "validations": [
            {"name": "choices", "value": '["Anna", "BILLY"]'},
        ]
    }
    assert choices_from_metafield_definition(raw) == ["Anna", "BILLY"]


def test_shopify_product_set_input_omits_invalid_choice_and_metaobject_metafields():
    fields = {
        "title": "Cabinet",
        "custom_brand": "Unknown Vendor",
        "custom_collection": "Cabinets",
        "custom_taxonomy": "Not a metaobject gid",
    }
    defs = {
        "custom_brand": {
            "namespace": "custom",
            "key": "brand",
            "type": "list.single_line_text_field",
            "choices": ["Anna", "Home Surplus"],
        },
        "custom_collection": {
            "namespace": "custom",
            "key": "collection",
            "type": "list.single_line_text_field",
            "choices": ["Cabinets", "Doors"],
        },
        "custom_taxonomy": {
            "namespace": "custom",
            "key": "taxonomy",
            "type": "metaobject_reference",
        },
    }

    product = map_payload_to_product_set_input("CSG-BC33U", fields, 99.0, metafield_defs=defs)
    metafields = {(m["namespace"], m["key"]): m for m in product.get("metafields", [])}

    assert ("custom", "brand") not in metafields
    assert metafields[("custom", "collection")]["value"] == '["Cabinets"]'
    assert ("custom", "taxonomy") not in metafields


def test_serialize_shopify_rich_text_wraps_plain_text():
    value = serialize_shopify_metafield_value("Hello world", "rich_text_field")
    parsed = json.loads(value)
    assert parsed["type"] == "root"
    assert parsed["children"][0]["children"][0]["value"] == "Hello world"


def test_shopify_product_set_input_skips_metafields_when_registry_empty():
    fields = {
        "title": "Cabinet",
        "door_style": "Double",
        "unknown_field": "drop me",
    }

    product = map_payload_to_product_set_input("ASG-B12", fields, 99.0, metafield_defs={})

    assert "metafields" not in product


def test_shopify_product_set_input_serializes_list_metafield_from_registry():
    fields = {
        "title": "Cabinet",
        "custom_door_style": "Double",
    }
    defs = {
        "custom_door_style": {
            "namespace": "custom",
            "key": "door_style",
            "type": "list.single_line_text_field",
        },
    }

    product = map_payload_to_product_set_input("ASG-B12", fields, 99.0, metafield_defs=defs)
    metafields = {(m["namespace"], m["key"]): m for m in product["metafields"]}

    assert metafields[("custom", "door_style")]["value"] == '["Double"]'


def test_shopify_product_set_input_skips_unregistered_metafields_when_registry_present():
    fields = {
        "title": "Cabinet",
        "known_field": "yes",
        "unknown_field": "drop me",
    }
    defs = {
        "known_field": {"namespace": "custom", "key": "known_field", "type": "single_line_text_field"},
    }

    product = map_payload_to_product_set_input("ASG-B12", fields, 99.0, metafield_defs=defs)
    keys = {(m["namespace"], m["key"]) for m in product.get("metafields", [])}

    assert ("custom", "known_field") in keys
    assert ("custom", "unknown_field") not in keys


def test_shopify_product_set_input_serializes_typed_metafields():
    fields = {
        "title": "Cabinet",
        "is_active_flag": "1",
        "door_count": "2",
        "width_inches": "12.5",
        "spec_json": ["a", "b"],
    }
    defs = {
        "is_active_flag": {"namespace": "custom", "key": "is_active_flag", "type": "boolean"},
        "door_count": {"namespace": "custom", "key": "door_count", "type": "number_integer"},
        "width_inches": {"namespace": "custom", "key": "width_inches", "type": "number_decimal"},
        "spec_json": {"namespace": "custom", "key": "spec_json", "type": "json"},
    }

    product = map_payload_to_product_set_input("ASG-B12", fields, 99.0, metafield_defs=defs)
    metafields = {(m["namespace"], m["key"]): m for m in product["metafields"]}

    assert metafields[("custom", "is_active_flag")]["value"] == "true"
    assert metafields[("custom", "door_count")]["value"] == "2"
    assert metafields[("custom", "width_inches")]["value"] == "12.5"
    assert metafields[("custom", "spec_json")]["value"] == '["a", "b"]'
