from rest_framework import status
from rest_framework.exceptions import ValidationError

from api.models import AuditTrail, AuditTrailDetails
from api.services.invigilator_assign import assign_invigilators_to_sessions
from api.translation import __
from api.utils import get_exception_detail, get_ip, log_critical_error
from api.validator import BaseValidator
from api.views.admin.base import AdminApiBase


class SessionAssignInvigilator(AdminApiBase):
    def validate_request(self, request):
        rules = {
            "id": "required|array|exists:api.EsSession,id",
        }
        attribute = {
            "id": "ID",
        }
        validator = BaseValidator(request.data, rules, attribute)
        error = validator.validate()
        if error:
            raise ValidationError(error)

        session_ids = request.data.get("id") or []
        return list(dict.fromkeys(session_ids))

    def post(self, request):
        try:
            session_ids = self.validate_request(request)
            result = assign_invigilators_to_sessions(session_ids, request.user.id)

            if result["old_data"] or result["new_data"]:
                audit_trail = AuditTrail.objects.create(
                    user_id=request.user.id,
                    type=self.audit_type,
                    ip_address=get_ip(request),
                )
                AuditTrailDetails.custom_insert(
                    audit_trail=audit_trail,
                    action="session_assign_invigilator",
                    remark_param={
                        "name": ",".join(result["session_names"]),
                    },
                    new_data=result["new_data"],
                    old_data=result["old_data"],
                )

            return self.api_response(data={"list": result["list"]})
        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)
