import json
from django.db import models
from django.conf import settings

from api.translation import __


class UserConstraintSetting(models.Model):
    MODE_TO_CODE = {
        "never": 0,
        "usually": 1,
        "always": 2,
    }
    id = models.BigAutoField(primary_key=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,related_name="constraint_setting")
    type = models.CharField(max_length=200)
    mode = models.SmallIntegerField(default=MODE_TO_CODE['always'])

    TYPE = {
        'avoid_double_booking_student_set',
        'avoid_double_booking_location',
        'avoid_double_booking_staff_member',
        'time_free_block',
        'time_maximum_hours',
        'time_maximum_work_span',
        'time_resource_break',
        'activity_sequencing',
        'activity_same_time',
        'activity_suggested_time',
        'other_avoid_concurrency',
        'other_travel',
        'other_unavailability',
        'location_capacity',
    }

    # group for FE, so FE no need hardcode to group it
    TYPE_GROUP = {
        "avoid_double_booking": [
            'avoid_double_booking_student_set',
            'avoid_double_booking_location',
            'avoid_double_booking_staff_member',
        ],
        "time": [
            'time_free_block',
            'time_maximum_hours',
            'time_maximum_work_span',
            'time_resource_break',
        ],
        "activity": [
            'activity_sequencing',
            'activity_same_time',
            'activity_suggested_time',
        ],
        "other": [
            'other_avoid_concurrency',
            'other_travel',
            'other_unavailability',
            'location_capacity',
        ]
    }

    class Meta:
        db_table = "user_constraint_setting"
        constraints = [
            models.UniqueConstraint(fields=["user", "type"], name="unique_user_type")
        ]

    @staticmethod
    def get_setting(user_id):
        """
        wont store all settings to this table, so when user start adjust only will store the setting, else will used default
        """
        setting = {
            val: {
                "id": val,
                "name": __("attr." + val),
                "mode": UserConstraintSetting.MODE_TO_CODE['always'],
            }
            for val in UserConstraintSetting.TYPE
        }

        custom_setting = UserConstraintSetting.objects.filter(user_id=user_id).values_list('type','mode')
        # merge default_setting with custom setting
        for type, mode in custom_setting:
            if type in setting:
                setting[type]["mode"] = mode

        return list(setting.values())

    @staticmethod
    def group_settings_data(settings_list):
        """
        @param settings_list: result from get_setting
        Format the data for FE
        """
        # 1. Convert the flat list into a quick lookup dictionary: {id: setting_dict}
        settings_lookup = {item["id"]: item for item in settings_list}

        # 2. Build the new structured dictionary
        grouped_result = {}

        for group_name, type_list in UserConstraintSetting.TYPE_GROUP.items():
            # Build the wrapper structure for this group
            grouped_result[group_name] = {
                "name": __("attr." + group_name),  # Translates the group title (e.g., "group.avoid_double_booking")
                "type": []
            }

            # Populate the "type" array with matching settings objects
            for type_key in type_list:
                if type_key in settings_lookup:
                    grouped_result[group_name]["type"].append(settings_lookup[type_key])

        return list(grouped_result.values())

    @staticmethod
    def get_rules():
        rules = {
            "mode": [
                {
                    "id": val,
                    "name": __(f"attr.user_constraint_setting_mode_name.{val}")
                }
                for key, val in UserConstraintSetting.MODE_TO_CODE.items()
            ],
        }
        return rules

    @staticmethod
    def kafka_group_settings_data(settings_list):
        """
        @param settings_list: result from get_setting
        Format the data for Kafka
        """
        grouped_result = {item["id"]: item['mode'] for item in settings_list}

        return grouped_result
