import ast

from django.views.generic import detail
from django.views.generic import detail
from rest_framework import status
from rest_framework.exceptions import ValidationError

from api.helper.audit_trail_helper import build_field_changes
from api.models import AuditTrail, User
from api.models.audit_trail_details import AuditTrailDetails as AuditTrailDetailsModel
from api.translation import __
from api.utils import log_critical_error, get_exception_detail
from api.validator import BaseValidator
from api.views.admin.base import AdminApiBase

class AuditTrailDetails(AdminApiBase):
	# Override base default "name" sorting because audit_trail has no name field.
	list_default_order_column = "-created_at"

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

	def post(self, request):
		try:
			self.api_log_skip_outgoing_data = True
			self.validate_request(request)
			data = self.get_data(request)
			return self.api_response(data=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)

	def get_data(self, request):
		details = AuditTrailDetailsModel.objects.select_related("audit_trail")
		detail_id = request.data.get("id")
		audit_trail_type = AuditTrail.TYPE
		audit_trail_type = {value: key for key, value in audit_trail_type.items()}

		if detail_id in [None, ""]:
			raise ValidationError({
				"error": "The id field is required.",
				"errors": {
					"id": ["The id field is required."]
				}
			})

		if isinstance(detail_id, (list, tuple, set)):
			raise ValidationError({
				"error": "The id field must be a single value.",
				"errors": {
					"id": ["The id field must be a single value."]
				}
			})

		detail = details.filter(id=detail_id).first()
		if not detail:
			raise ValidationError({
				"error": __("validation.invalid", field=__("attr.id")),
				"errors": {
					"id": __("validation.invalid", field=__("attr.id"))
				}
			})

		trail = detail.audit_trail
		if detail.remark_param:
			if isinstance(detail.remark_param, dict):
				remark_param = detail.remark_param
			else:
				try:
					remark_param = ast.literal_eval(detail.remark_param)
				except (ValueError, SyntaxError):
					remark_param = {}
		else:
			remark_param = {}

		if not isinstance(remark_param, dict):
			remark_param = {}
        
		remark_name = remark_param.get("name") or remark_param.get("code") or remark_param.get("ids") or ""

		remark_name_list = []
		if isinstance(remark_name, (list, tuple, set)):
			remark_name_list = list(map(str, remark_name))
			remark_name = ", ".join(map(str, remark_name))
		elif remark_name is None:
			remark_name = ""
		else:
			remark_name = str(remark_name)
			remark_name_list = [x.strip() for x in remark_name.split(",") if x.strip()]

		action_text = __(f"audit_trail.action.admin.{detail.action}", **remark_param)

		user_name = ""
		if trail.user_id:
			r = User.objects.filter(id=trail.user_id).first()
			user_name = r.name if r else ""

		return {
			"id": detail.id,
			"audit_trail_id": trail.id,
			"user_id": trail.user_id,
			"user_name": user_name,
			"type": trail.type,
			"type_text": __(f"audit_trail.type.{audit_trail_type.get(trail.type, '')}"),
			"action": detail.action,
			"action_text": action_text,
			"remark_text": remark_name,
			"remark_param": remark_param,
			"field_changes": build_field_changes(detail.action, detail.old_data, detail.new_data, extra_data={"remark_name": remark_name_list}),
			"created_at": detail.created_at,
		}

