import re

from heksher import Setting, ThreadHeksherClient

from utils import generate_setting_name


def test_get_settings(app_client, heksher_client: ThreadHeksherClient):
    setting_name_int = generate_setting_name()
    setting_description_int = "me control cake temp"
    setting_default_value_int = 5
    setting_features_int = ["user"]
    setting_name_str = generate_setting_name()
    setting_description_str = "me control the universe"
    setting_default_value_str = "just dance, gonna be alright!"
    setting_features_str = ["user", "theme"]

    Setting(
        setting_name_int,
        int,
        setting_features_int,
        setting_default_value_int,
        metadata={"description": setting_description_int},
    )
    Setting(
        setting_name_str,
        str,
        setting_features_str,
        setting_default_value_str,
        metadata={"description": setting_description_str},
    )

    heksher_client.reload()

    response = app_client.get("/api/v1/settings")
    response.raise_for_status()

    result = response.json()
    assert {
        "name": setting_name_int,
        "configurable_features": setting_features_int,
        "type": "int",
        "default_value": setting_default_value_int,
        "description": setting_description_int,
    } in result
    assert {
        "name": setting_name_str,
        "configurable_features": setting_features_str,
        "type": "str",
        "default_value": setting_default_value_str,
        "description": setting_description_str,
    } in result


def test_get_settings_rules(app_client, heksher_client: ThreadHeksherClient):
    setting_name = generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 5
    setting_features = ["user", "theme"]
    Setting(
        setting_name,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )

    heksher_client.reload()

    rules = [
        {
            "value": 30,
            "feature_values": {"user": "pita", "theme": "sabich"},
            "setting": setting_name,
            "information": "funfun",
        },
        {
            "value": 1,
            "feature_values": {"user": "pita", "theme": "iraqish"},
            "setting": setting_name,
            "information": "funfun2",
        },
    ]

    def create_rule(rule) -> int:
        response = app_client.post("/api/v1/rule", json=rule)
        response.raise_for_status()
        return response.json()["rule_id"]

    for rule in rules:
        rule["rule_id"] = create_rule(rule)

    response = app_client.get(f"/api/v1/settings/{setting_name}/rules")
    result_rules = response.json()
    user = app_client.headers["X-FORWARDED-EMAIL"]

    # Align input data to the expected result data.
    for rule in rules:
        rule.pop("setting")
        rule["context_features"] = rule.pop("feature_values")
    # Assert data generated by server, and remove it for easier comparison.
    for rule in result_rules:
        assert rule.pop("date")
        assert rule.pop("added_by") == user

    assert result_rules == rules

    for rule in rules:
        app_client.delete(f'/api/v1/rule/{rule["rule_id"]}').raise_for_status()


def test_csv_export(app_client, heksher_client: ThreadHeksherClient):
    setting_name_1 = 'a' + generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 5
    setting_features = ["user", "theme"]
    Setting(
        setting_name_1,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )
    setting_name_2 = 'b' + generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 12
    setting_features = ["trust", "theme"]
    Setting(
        setting_name_2,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )

    heksher_client.reload()

    rules = [
        {
            "value": 30,
            "feature_values": {"user": "pita", "theme": "sabich"},
            "setting": setting_name_1,
            "information": "funfun",
        },
        {
            "value": 1,
            "feature_values": {"theme": "iraqish"},
            "setting": setting_name_1,
            "information": "funfun2",
        },
        {
            "value": 2,
            "feature_values": {"theme": "iraqish"},
            "setting": setting_name_2,
            "information": "funfun3",
        },
        {
            "value": 11,
            "feature_values": {"trust": "none"},
            "setting": setting_name_2,
            "information": "funfun4",
        },
    ]

    for rule in rules:
        response = app_client.post("/api/v1/rule", json=rule)
        response.raise_for_status()

    csv_resp = app_client.get('/api/v1/settings/export/csv')
    csv_resp.raise_for_status()
    csv = csv_resp.json()['csv']
    csv, n = re.subn(',[T0-9:.-]+\r\n', ',$NOW$\r\n', csv)
    assert n == 4
    assert csv == (
        'setting,user,trust,theme,value,added_by,information,date\r\n'
        f'{setting_name_1},pita,,sabich,30,<EMAIL>,funfun,$NOW$\r\n'
        f'{setting_name_1},,,iraqish,1,<EMAIL>,funfun2,$NOW$\r\n'
        f'{setting_name_2},,,iraqish,2,<EMAIL>,funfun3,$NOW$\r\n'
        f'{setting_name_2},,none,,11,<EMAIL>,funfun4,$NOW$\r\n'
    )

import re

from heksher import Setting, ThreadHeksherClient

from utils import generate_setting_name


def test_get_settings(app_client, heksher_client: ThreadHeksherClient):
    setting_name_int = generate_setting_name()
    setting_description_int = "me control cake temp"
    setting_default_value_int = 5
    setting_features_int = ["user"]
    setting_name_str = generate_setting_name()
    setting_description_str = "me control the universe"
    setting_default_value_str = "just dance, gonna be alright!"
    setting_features_str = ["user", "theme"]

    Setting(
        setting_name_int,
        int,
        setting_features_int,
        setting_default_value_int,
        metadata={"description": setting_description_int},
    )
    Setting(
        setting_name_str,
        str,
        setting_features_str,
        setting_default_value_str,
        metadata={"description": setting_description_str},
    )

    heksher_client.reload()

    response = app_client.get("/api/v1/settings")
    response.raise_for_status()

    result = response.json()
    assert {
        "name": setting_name_int,
        "configurable_features": setting_features_int,
        "type": "int",
        "default_value": setting_default_value_int,
        "description": setting_description_int,
    } in result
    assert {
        "name": setting_name_str,
        "configurable_features": setting_features_str,
        "type": "str",
        "default_value": setting_default_value_str,
        "description": setting_description_str,
    } in result


def test_get_settings_rules(app_client, heksher_client: ThreadHeksherClient):
    setting_name = generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 5
    setting_features = ["user", "theme"]
    Setting(
        setting_name,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )

    heksher_client.reload()

    rules = [
        {
            "value": 30,
            "feature_values": {"user": "pita", "theme": "sabich"},
            "setting": setting_name,
            "information": "funfun",
        },
        {
            "value": 1,
            "feature_values": {"user": "pita", "theme": "iraqish"},
            "setting": setting_name,
            "information": "funfun2",
        },
    ]

    def create_rule(rule) -> int:
        response = app_client.post("/api/v1/rule", json=rule)
        response.raise_for_status()
        return response.json()["rule_id"]

    for rule in rules:
        rule["rule_id"] = create_rule(rule)

    response = app_client.get(f"/api/v1/settings/{setting_name}/rules")
    result_rules = response.json()
    user = app_client.headers["X-FORWARDED-EMAIL"]

    # Align input data to the expected result data.
    for rule in rules:
        rule.pop("setting")
        rule["context_features"] = rule.pop("feature_values")
    # Assert data generated by server, and remove it for easier comparison.
    for rule in result_rules:
        assert rule.pop("date")
        assert rule.pop("added_by") == user

    assert result_rules == rules

    for rule in rules:
        app_client.delete(f'/api/v1/rule/{rule["rule_id"]}').raise_for_status()


def test_csv_export(app_client, heksher_client: ThreadHeksherClient):
    setting_name_1 = 'a' + generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 5
    setting_features = ["user", "theme"]
    Setting(
        setting_name_1,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )
    setting_name_2 = 'b' + generate_setting_name()
    setting_description = "me control cake temp"
    setting_default_value = 12
    setting_features = ["trust", "theme"]
    Setting(
        setting_name_2,
        int,
        setting_features,
        setting_default_value,
        metadata={"description": setting_description},
    )

    heksher_client.reload()

    rules = [
        {
            "value": 30,
            "feature_values": {"user": "pita", "theme": "sabich"},
            "setting": setting_name_1,
            "information": "funfun",
        },
        {
            "value": 1,
            "feature_values": {"theme": "iraqish"},
            "setting": setting_name_1,
            "information": "funfun2",
        },
        {
            "value": 2,
            "feature_values": {"theme": "iraqish"},
            "setting": setting_name_2,
            "information": "funfun3",
        },
        {
            "value": 11,
            "feature_values": {"trust": "none"},
            "setting": setting_name_2,
            "information": "funfun4",
        },
    ]

    for rule in rules:
        response = app_client.post("/api/v1/rule", json=rule)
        response.raise_for_status()

    csv_resp = app_client.get('/api/v1/settings/export/csv')
    csv_resp.raise_for_status()
    csv = csv_resp.json()['csv']
    csv, n = re.subn(',[T0-9:.-]+\r\n', ',$NOW$\r\n', csv)
    assert n == 4
    assert csv == (
        'setting,user,trust,theme,value,added_by,information,date\r\n'
        f'{setting_name_1},pita,,sabich,30,<EMAIL>,funfun,$NOW$\r\n'
        f'{setting_name_1},,,iraqish,1,<EMAIL>,funfun2,$NOW$\r\n'
        f'{setting_name_2},,,iraqish,2,<EMAIL>,funfun3,$NOW$\r\n'
        f'{setting_name_2},,none,,11,<EMAIL>,funfun4,$NOW$\r\n'
    )

# Align input data to the expected result data. # Assert data generated by server, and remove it for easier comparison.