from faker import Faker
from utils import constants, roles, var_names
import configuration as configs
import factory
import pytz
import random

fake = Faker()

# Central map of fields to types or semantic categories
FIELD_TYPE_MAP = {
    
    # Payment Info
    "brand": "str",
    "last_four": "str",
    "card_token": "dict",  # Complex type
    "handler": "str",
    "is_default": "bool",
}

class PaymentInfoFactory(factory.Factory):
    """
    Factory to generate mock payment information.
    """
    class Meta:
        model = dict

    brand = factory.LazyAttribute(lambda _: random.choice(["visa", "mastercard", "amex"]))
    last_four = factory.LazyAttribute(lambda _: f"{random.randint(1000, 9999)}")
    card_token = factory.LazyAttribute(lambda _: {
        var_names.customer_id: str(fake.uuid4()),
        var_names.payment_method: str(fake.uuid4()),
    })
    handler = factory.LazyAttribute(lambda _: random.choice(configs.allowed_payment_handlers))
    is_default = factory.LazyAttribute(lambda _: fake.boolean())


    def get_invalid_values(field_name):
        """
        Returns a list of invalid but type-consistent or semantically incorrect
        values for a given field. Prevents type errors but supports validation testing.
        """
        expected_type = FIELD_TYPE_MAP.get(field_name)

        if field_name == "card_token":
            return [
                None,
                {},
                {"key": "value"},
                {var_names.customer_id: None},
                {var_names.payment_method: None},
                {var_names.customer_id: "", var_names.payment_method: ""},
                {var_names.customer_id: "abc"},  # Missing payment_method
                {var_names.payment_method: "xyz"},  # Missing customer_id
                {var_names.customer_id: "abc", "wrong_key": "xyz"},  # Invalid key set
            ]

        elif field_name in ["brand"]:
            return [
                "123 Main St; drop table users;",  # SQL injection attempt
                "456 Elm St, insert into users (name) values ('test');",  # SQL injection attempt
                "789 Oak St, delete from users where id=1;",  # SQL injection attempt
            ]

        elif field_name == "last_four":
            return [
                "",  # Empty string
                "@@!!##",  # Special characters
                fake.text(max_nb_chars=300),  # Long random text
                "12345abcde"  # Alphanumeric string, not a valid
            ]
        elif expected_type == "str":    
            return [
                "",
                "   ",
                fake.text(max_nb_chars=300),
                "@@!!##",
            ]
        

        elif expected_type == "int":
            return [-999, 0, 999999999999999]
        elif expected_type == "bool":
            return ["yes", "no", "truthy", 1, 0]
        elif expected_type == "list":
            return [[], ["", "", ""]]
        elif expected_type == "dict":
            return [{}, {"key": ""}]
        else:
            return [None]  # fallback