import json

from rest_framework import status
from rest_framework.exceptions import ValidationError

from api.models.es_department import EsDepartment
from api.models.es_exam_period import EsExamPeriod
from api.models.es_exam_requirement import EsExamRequirement
from api.models.es_invigilator import EsInvigilator
from api.models.es_invigilator_role import EsInvigilatorRole
from api.models.es_location import EsLocation
from api.models.es_pos import EsPos
from api.models.es_session_start import EsSessionStart
from api.models.es_setting import EsSetting
from api.models.es_staff import EsStaff
from api.models.es_student import EsStudent
from api.models.es_student_group import EsStudentGroup
from api.models.es_suitability import EsSuitability
from api.models.es_tag import EsTag
from api.models.es_zone import EsZone
from api.translation import __
from api.utils import get_exception_detail, log_critical_error
from api.validator import BaseValidator
from api.views.admin.base import AdminApiBase


class ImportGetInformation(AdminApiBase):
    def validate_request(self, request, import_tables):
        destination_string = ",".join(str(v) for v in import_tables)
        rules = {
            "destination": "nullable|in:" + destination_string,
        }
        validator = BaseValidator(request.data, rules, {})
        error = validator.validate()
        if error:
            raise ValidationError(error)

    def post(self, request):
        try:
            setting = EsSetting.objects.filter(param="import_tables").first()
            if not setting or not setting.value:
                return self.api_response(error=__("import.no_importables"), code=status.HTTP_400_BAD_REQUEST)

            import_tables = json.loads(setting.value)
            return_data = []

            if request.data.get("destination"):
                self.validate_request(request, import_tables)
                destination = request.data.get("destination")

                model_map = {
                    "es_zone": EsZone,
                    "es_department": EsDepartment,
                    "es_tag": EsTag,
                    "es_suitability": EsSuitability,
                    "es_pos": EsPos,
                    "es_student_group": EsStudentGroup,
                    "es_invigilator_role": EsInvigilatorRole,
                    "es_staff": EsStaff,
                    "es_student": EsStudent,
                    "es_location": EsLocation,
                    "es_invigilator": EsInvigilator,
                    "es_exam_period": EsExamPeriod,
                    "es_session_start": EsSessionStart,
                    "es_exam_requirement": EsExamRequirement,
                    "es_suitability_invigilator": EsSuitability,
                    "es_suitability_location": EsSuitability,
                    "es_invigilator_roles": EsInvigilator,
                    "es_student_student_group": EsStudent,
                    "es_exam_period_unavailability": EsExamPeriod,
                    "es_exam_requirement_student": EsExamRequirement,
                    "es_exam_req_invigilator_s": EsExamRequirement,
                    "es_exam_req_location_s": EsExamRequirement,
                }

                sub_model_map = {
                    "es_suitability_invigilator": "SUITABILITY_INVIGILATOR",
                    "es_suitability_location": "SUITABILITY_LOCATION",
                    "es_invigilator_roles": "INVIGILATOR_ROLES",
                    "es_student_student_group": "STUDENT_STUDENT_GROUP",
                    "es_exam_period_unavailability": "EXAM_PERIOD_UNAVAILABILITY",
                    "es_exam_requirement_student": "EXAM_REQUIREMENT_STUDENT",
                    "es_exam_req_invigilator_s": "EXAM_REQ_INVIGILATOR_S",
                    "es_exam_req_location_s": "EXAM_REQ_LOCATION_S",
                }

                table = model_map.get(destination)
                if not table:
                    return self.api_response(data={})

                if destination in sub_model_map:
                    import_config = getattr(table, sub_model_map[destination], {})
                    rules = import_config.get("IMPORT_RULES", {})
                else:
                    rules = getattr(table, "IMPORT_RULES", {})

                for key, value in rules.items():
                    return_data.append(
                        {
                            "id": key,
                            "name": __("import_attr." + key),
                            "rules": value,
                        }
                    )
            else:
                for table in import_tables:
                    return_data.append(
                        {
                            "table": table,
                            "name": __("db_table_name." + table),
                        }
                    )
                return_data.sort(key=lambda x: str(x["name"]))

            return self.api_response(data={"data": return_data})
        except ValidationError as e:
            first_message = e.detail["error"]
            errors = e.detail["errors"]
            return self.api_response(error=first_message, errors=errors, code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            e_details = get_exception_detail(e)
            log_critical_error(user_id=None, descr=e_details["descr"], url=e_details["url"], trace=e_details["trace"])
            return self.api_response(error=__("message.internal_server_error"), code=status.HTTP_500_INTERNAL_SERVER_ERROR)
