from decimal import Decimal, InvalidOperation

from collections import defaultdict

from django.db import router, transaction
from django.db.models.deletion import Collector, ProtectedError, RestrictedError
from django.contrib.auth import get_user_model
from django.utils import timezone
from rest_framework import mixins, permissions, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
from rest_framework.response import Response
from drf_spectacular.utils import (
    OpenApiParameter,
    OpenApiTypes,
    extend_schema,
    extend_schema_view,
)
from iems_backend.viewsets import NoPutCRUDViewSet, NoReadUpsertViewSet
from users.permissions import (
    IsAdminOrReadOnly,
    IsAdminOrReadCreateOnly,
    IsAdminUserRole,
    is_admin_user,
)
from .models import (
    SubmissionType,
    CommodityCategory,
    CommodityType,
    UnitOfMeasurement,
    UnitConversion,
    SubmissionStatus,
    CollectionCategory,
    CollectionType,
    MetadataDeletionRequest,
    Submission,
    ImportSubmission,
    ExportSubmission,
    RevenueFineSubmission,
    HealthInspectionSubmission,
    DestructionSubmission,
    Document,
    SubmissionStatusHistory,
)
from .serializers import (
    SubmissionTypeSerializer,
    CommodityCategorySerializer,
    CommodityTypeSerializer,
    UnitOfMeasurementSerializer,
    UnitConversionSerializer,
    SubmissionStatusSerializer,
    CollectionCategorySerializer,
    CollectionTypeSerializer,
    MetadataDeletionRequestSerializer,
    MetadataDeletionRequestDecisionSerializer,
    UnifiedSubmissionReadSerializer,
    ImportSubmissionReadSerializer,
    ImportSubmissionWriteSerializer,
    ExportSubmissionReadSerializer,
    ExportSubmissionWriteSerializer,
    RevenueFineSubmissionReadSerializer,
    RevenueFineSubmissionWriteSerializer,
    HealthInspectionSubmissionReadSerializer,
    HealthInspectionSubmissionWriteSerializer,
    DestructionSubmissionReadSerializer,
    DestructionSubmissionWriteSerializer,
    DocumentSerializer,
    SubmissionStatusHistorySerializer,
    SubmissionStatusChangeSerializer,
)

User = get_user_model()


def _decimal_text(value):
    number = Decimal(str(value))
    text = format(number, "f")
    if "." in text:
        text = text.rstrip("0").rstrip(".")
    return text or "0"

class BaseSubmissionViewSet(NoReadUpsertViewSet):
    """
    Base ViewSet for all submission types.
    Handles automatic user assignment and switching between Read/Write serializers.
    """

    permission_classes = [permissions.IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    def get_serializer_class(self):
        if self.action in ["list", "retrieve"]:
            return self.read_serializer_class
        return self.write_serializer_class

    @staticmethod
    def _get_default_status():
        status = SubmissionStatus.objects.filter(code__iexact="PENDING").first()
        if status:
            return status

        status = SubmissionStatus.objects.filter(name__iexact="Pending").first()
        if status:
            return status

        raise ValidationError(
            {"status": "Default submission status 'PENDING' is not configured."}
        )

    def perform_create(self, serializer):
        # Automatically set audit fields and checkpoint on create
        status = self._get_default_status()
        user_checkpoint = getattr(self.request.user, "checkpoint", None)
        if not user_checkpoint:
            raise ValidationError(
                {
                    "checkpoint": (
                        "No checkpoint is assigned to this user. "
                        "Please contact an administrator."
                    )
                }
            )
        serializer.save(
            created_by=self.request.user,
            updated_by=self.request.user,
            status=status,
            checkpoint=user_checkpoint,
        )

    def perform_update(self, serializer):
        serializer.save(updated_by=self.request.user)
    
    def get_queryset(self):
        queryset = super().get_queryset()
        current_user = self.request.user

        if is_admin_user(current_user):
            return queryset

        user_checkpoint = getattr(current_user, "checkpoint", None)
        if not user_checkpoint:
            return queryset.none()

        return queryset.filter(checkpoint=user_checkpoint)

    # Nepali date filtering available on all child submission ViewSets
    filterset_fields = (
        "submission_type",
        "status__code",
        "status__name",
        "checkpoint",
        "created_by",
        "nepali_year",
        "nepali_month",
        "nepali_quarter",
    )
    search_fields = ("tracking_code", "refrence_no", "remarks")
    ordering_fields = ("submitted_at", "created_at", "updated_at", "tracking_code", "nepali_year", "nepali_month")
    ordering = ("-submitted_at",)


# ==========================================
# Supporting Model ViewSets
# ==========================================


@extend_schema(tags=["Submission Types"])
class SubmissionTypeViewSet(NoPutCRUDViewSet):
    queryset = SubmissionType.objects.all()
    serializer_class = SubmissionTypeSerializer
    permission_classes = [IsAdminOrReadOnly]


@extend_schema(tags=["Commodity Categories"])
class CommodityCategoryViewSet(NoPutCRUDViewSet):
    queryset = CommodityCategory.objects.all()
    serializer_class = CommodityCategorySerializer
    permission_classes = [IsAdminOrReadCreateOnly]

    @extend_schema(
        tags=["Commodity Categories"],
        responses=CommodityTypeSerializer(many=True),
        description="List commodity types for a specific commodity category.",
    )
    @action(detail=True, methods=["get"], url_path="types")
    def types(self, request, pk=None):
        category = self.get_object()
        queryset = CommodityType.objects.select_related("category").filter(
            category=category
        )
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = CommodityTypeSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = CommodityTypeSerializer(queryset, many=True)
        return Response(serializer.data)


@extend_schema(tags=["Commodity Types"])
class CommodityTypeViewSet(NoPutCRUDViewSet):
    queryset = CommodityType.objects.select_related("category").all()
    serializer_class = CommodityTypeSerializer
    permission_classes = [IsAdminOrReadCreateOnly]

    def get_queryset(self):
        queryset = super().get_queryset()
        category_id = self.request.query_params.get("category")
        if category_id:
            queryset = queryset.filter(category_id=category_id)
        return queryset


@extend_schema(tags=["Units of Measurement"])
class UnitOfMeasurementViewSet(NoPutCRUDViewSet):
    queryset = UnitOfMeasurement.objects.all()
    serializer_class = UnitOfMeasurementSerializer
    permission_classes = [IsAdminOrReadOnly]


@extend_schema(tags=["Unit Conversions"])
class UnitConversionViewSet(NoPutCRUDViewSet):
    queryset = UnitConversion.objects.select_related("from_unit", "to_unit").all()
    serializer_class = UnitConversionSerializer
    permission_classes = [IsAdminOrReadOnly]
    filterset_fields = ("from_unit", "to_unit", "from_unit__code", "to_unit__code")
    search_fields = ("from_unit__name", "from_unit__code", "to_unit__name", "to_unit__code")
    ordering_fields = ("created_at", "updated_at", "factor")
    ordering = ("from_unit__name", "to_unit__name")

    @staticmethod
    def _resolve_unit(identifier, field_name):
        if not identifier:
            raise ValidationError({field_name: "This query parameter is required."})

        unit = UnitOfMeasurement.objects.filter(code__iexact=identifier).first()
        if unit:
            return unit

        try:
            unit = UnitOfMeasurement.objects.filter(pk=identifier).first()
        except (TypeError, ValueError):
            unit = None

        if unit:
            return unit

        raise ValidationError(
            {
                field_name: (
                    "Unit not found. Provide a valid unit ID or unit code "
                    f"for '{field_name}'."
                )
            }
        )

    @extend_schema(
        tags=["Unit Conversions"],
        parameters=[
            OpenApiParameter(
                name="value",
                required=True,
                type=str,
                location=OpenApiParameter.QUERY,
                description="Numeric value to convert (e.g. 5 or 12.75).",
            ),
            OpenApiParameter(
                name="from_unit",
                required=True,
                type=str,
                location=OpenApiParameter.QUERY,
                description="Unit ID or code for source unit (e.g. KG).",
            ),
            OpenApiParameter(
                name="to_unit",
                required=True,
                type=str,
                location=OpenApiParameter.QUERY,
                description="Unit ID or code for target unit (e.g. GM).",
            ),
        ],
        description=(
            "Convert a numeric value between related units. "
            "Uses direct conversion ratio, or inverse if reverse ratio exists."
        ),
    )
    @action(detail=False, methods=["get"], url_path="convert")
    def convert(self, request):
        value_raw = request.query_params.get("value")
        from_identifier = request.query_params.get("from_unit")
        to_identifier = request.query_params.get("to_unit")

        if value_raw is None:
            raise ValidationError({"value": "This query parameter is required."})

        try:
            value = Decimal(str(value_raw))
        except (TypeError, InvalidOperation):
            raise ValidationError(
                {"value": "Enter a valid decimal number for conversion."}
            )

        from_unit = self._resolve_unit(from_identifier, "from_unit")
        to_unit = self._resolve_unit(to_identifier, "to_unit")

        if from_unit.id == to_unit.id:
            conversion_factor = Decimal("1")
            converted_value = value
        else:
            conversion = UnitConversion.objects.filter(
                from_unit=from_unit, to_unit=to_unit
            ).first()
            reverse_conversion = None

            if conversion:
                conversion_factor = conversion.factor
            else:
                reverse_conversion = UnitConversion.objects.filter(
                    from_unit=to_unit, to_unit=from_unit
                ).first()
                if not reverse_conversion:
                    raise ValidationError(
                        {
                            "conversion": (
                                f"No conversion ratio configured between {from_unit.code} "
                                f"and {to_unit.code}."
                            )
                        }
                    )
                conversion_factor = Decimal("1") / reverse_conversion.factor

            converted_value = value * conversion_factor

        return Response(
            {
                "value": _decimal_text(value),
                "from_unit": {
                    "id": str(from_unit.id),
                    "name": from_unit.name,
                    "code": from_unit.code,
                    "dimension": from_unit.dimension,
                },
                "to_unit": {
                    "id": str(to_unit.id),
                    "name": to_unit.name,
                    "code": to_unit.code,
                    "dimension": to_unit.dimension,
                },
                "factor": _decimal_text(conversion_factor),
                "converted_value": _decimal_text(converted_value),
            }
        )


@extend_schema(tags=["Submission Statuses"])
class SubmissionStatusViewSet(NoPutCRUDViewSet):
    queryset = SubmissionStatus.objects.all()
    serializer_class = SubmissionStatusSerializer
    permission_classes = [IsAdminOrReadOnly]


@extend_schema(tags=["Collection Categories"])
class CollectionCategoryViewSet(NoPutCRUDViewSet):
    queryset = CollectionCategory.objects.all()
    serializer_class = CollectionCategorySerializer
    permission_classes = [IsAdminOrReadCreateOnly]

    @extend_schema(
        tags=["Collection Categories"],
        responses=CollectionTypeSerializer(many=True),
        description="List collection types for a specific collection category.",
    )
    @action(detail=True, methods=["get"], url_path="types")
    def types(self, request, pk=None):
        category = self.get_object()
        queryset = CollectionType.objects.select_related("category").filter(
            category=category
        )
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = CollectionTypeSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = CollectionTypeSerializer(queryset, many=True)
        return Response(serializer.data)


@extend_schema(tags=["Collection Types"])
class CollectionTypeViewSet(NoPutCRUDViewSet):
    queryset = CollectionType.objects.select_related("category").all()
    serializer_class = CollectionTypeSerializer
    permission_classes = [IsAdminOrReadCreateOnly]

    def get_queryset(self):
        queryset = super().get_queryset()
        category_id = self.request.query_params.get("category")
        if category_id:
            queryset = queryset.filter(category_id=category_id)
        return queryset


@extend_schema(tags=["Category/Type of Collection/Commodity Data Deletion Requests"])
class MasterDataDeletionRequestViewSet(
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.CreateModelMixin,
    viewsets.GenericViewSet,
):
    queryset = MetadataDeletionRequest.objects.select_related(
        "requested_by", "reviewed_by"
    ).all()
    serializer_class = MetadataDeletionRequestSerializer
    permission_classes = [IsAdminOrReadCreateOnly]
    filterset_fields = ("status", "target_type", "requested_by")
    search_fields = (
        "target_name",
        "reason",
        "review_note",
        "requested_by__name",
        "requested_by__email",
    )
    ordering_fields = ("created_at", "updated_at", "reviewed_at", "status")
    ordering = ("-created_at",)

    def get_queryset(self):
        queryset = super().get_queryset()
        if is_admin_user(self.request.user):
            return queryset
        return queryset.filter(requested_by=self.request.user)

    def perform_create(self, serializer):
        serializer.save(requested_by=self.request.user)

    def _validate_pending(self, delete_request):
        if delete_request.status != MetadataDeletionRequest.StatusChoices.PENDING:
            raise ValidationError({"status": "Only pending requests can be reviewed."})

    @staticmethod
    def _compute_deletion_impact(target_obj):
        using = router.db_for_write(target_obj.__class__, instance=target_obj)
        collector = Collector(using=using)
        collector.collect([target_obj])

        counts_by_model = defaultdict(int)
        for model, instances in collector.data.items():
            counts_by_model[model] += len(instances)

        for queryset in collector.fast_deletes:
            model = getattr(queryset, "model", None)
            if model is None:
                continue
            counts_by_model[model] += queryset.count()

        breakdown = [
            {"model": model._meta.label, "count": count}
            for model, count in counts_by_model.items()
        ]
        breakdown.sort(key=lambda item: (-item["count"], item["model"]))

        total = sum(item["count"] for item in breakdown)
        return {
            "total_records_including_target": total,
            "related_records": max(total - 1, 0),
            "breakdown": breakdown,
        }

    @extend_schema(
        tags=["Category/Type of Collection/Commodity Data Deletion Requests"],
        request=MetadataDeletionRequestDecisionSerializer,
        responses={200: MetadataDeletionRequestSerializer, 409: OpenApiTypes.OBJECT},
        description=(
            "Approve a pending master-data deletion request. "
            "If `confirm_deletion` is not true, returns a warning payload with "
            "deletion impact counts and does not delete."
        ),
    )
    @action(
        detail=True,
        methods=["post"],
        url_path="approve",
        permission_classes=[IsAdminUserRole],
    )
    def approve(self, request, pk=None):
        delete_request = self.get_object()
        self._validate_pending(delete_request)

        decision_serializer = MetadataDeletionRequestDecisionSerializer(data=request.data)
        decision_serializer.is_valid(raise_exception=True)

        target_obj = delete_request.resolve_target()
        if target_obj and not delete_request.target_name:
            delete_request.target_name = str(target_obj)

        if target_obj:
            try:
                deletion_impact = self._compute_deletion_impact(target_obj)
            except (ProtectedError, RestrictedError):
                raise ValidationError(
                    {
                        "deletion": (
                            "Deletion is blocked because protected related records exist."
                        )
                    }
                )

            if not decision_serializer.validated_data.get("confirm_deletion", False):
                return Response(
                    {
                        "requires_confirmation": True,
                        "message": (
                            "Approving this request will delete the target record and "
                            "related records."
                        ),
                        "deletion_impact": deletion_impact,
                    },
                    status=409,
                )

        with transaction.atomic():
            if target_obj:
                target_obj.delete()

            delete_request.status = MetadataDeletionRequest.StatusChoices.APPROVED
            delete_request.reviewed_by = request.user
            delete_request.reviewed_at = timezone.now()
            delete_request.review_note = decision_serializer.validated_data.get(
                "review_note"
            )
            delete_request.save(
                update_fields=[
                    "status",
                    "reviewed_by",
                    "reviewed_at",
                    "review_note",
                    "target_name",
                    "updated_at",
                ]
            )

        serializer = self.get_serializer(delete_request)
        return Response(serializer.data)

    @extend_schema(
        tags=["Category/Type of Collection/Commodity Data Deletion Requests"],
        request=MetadataDeletionRequestDecisionSerializer,
        responses=MetadataDeletionRequestSerializer,
        description="Deny a pending master-data deletion request without deleting data.",
    )
    @action(
        detail=True,
        methods=["post"],
        url_path="deny",
        permission_classes=[IsAdminUserRole],
    )
    def deny(self, request, pk=None):
        delete_request = self.get_object()
        self._validate_pending(delete_request)

        decision_serializer = MetadataDeletionRequestDecisionSerializer(data=request.data)
        decision_serializer.is_valid(raise_exception=True)

        delete_request.status = MetadataDeletionRequest.StatusChoices.DENIED
        delete_request.reviewed_by = request.user
        delete_request.reviewed_at = timezone.now()
        delete_request.review_note = decision_serializer.validated_data.get("review_note")
        delete_request.save(
            update_fields=[
                "status",
                "reviewed_by",
                "reviewed_at",
                "review_note",
                "updated_at",
            ]
        )

        serializer = self.get_serializer(delete_request)
        return Response(serializer.data)


@extend_schema(tags=["Documents"])
class DocumentViewSet(NoPutCRUDViewSet):
    queryset = Document.objects.select_related("submission", "uploaded_by").all()
    serializer_class = DocumentSerializer
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    def get_queryset(self):
        queryset = super().get_queryset()
        current_user = self.request.user

        if is_admin_user(current_user):
            return queryset

        user_checkpoint = getattr(current_user, "checkpoint", None)
        if not user_checkpoint:
            return queryset.none()

        return queryset.filter(submission__checkpoint=user_checkpoint)

    def perform_create(self, serializer):
        submission = serializer.validated_data["submission"]
        current_user = self.request.user

        if not is_admin_user(current_user):
            user_checkpoint = getattr(current_user, "checkpoint", None)
            if not user_checkpoint:
                raise ValidationError(
                    {
                        "checkpoint": (
                            "No checkpoint is assigned to this user. "
                            "Please contact an administrator."
                        )
                    }
                )
            if submission.checkpoint_id != user_checkpoint.id:
                raise ValidationError(
                    {
                        "submission": (
                            "You can only upload documents for submissions in "
                            "your assigned checkpoint."
                        )
                    }
                )

        serializer.save(uploaded_by=self.request.user)


@extend_schema(tags=["Submission Status History"])
class SubmissionStatusHistoryViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Status history is typically read-only or created via transition logic.
    """

    queryset = SubmissionStatusHistory.objects.select_related(
        "submission", "updated_by", "from_status", "to_status"
    ).all()
    serializer_class = SubmissionStatusHistorySerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        queryset = super().get_queryset()
        current_user = self.request.user

        if is_admin_user(current_user):
            return queryset

        user_checkpoint = getattr(current_user, "checkpoint", None)
        if not user_checkpoint:
            return queryset.none()

        return queryset.filter(submission__checkpoint=user_checkpoint)


@extend_schema_view(
    list=extend_schema(
        tags=["Submissions"],
        description=(
            "Admins can access all submissions. Staff users are restricted to "
            "their assigned checkpoint and can optionally filter by users "
            "within that same checkpoint. Submission manipulation is also "
            "restricted to the same checkpoint scope."
        ),
        parameters=[
            OpenApiParameter(
                name="user",
                type=str,
                location=OpenApiParameter.QUERY,
                description="Filter submissions by creator user UUID.",
            ),
            OpenApiParameter(
                name="checkpoint",
                type=str,
                location=OpenApiParameter.QUERY,
                description="Filter submissions by checkpoint UUID.",
            ),
            OpenApiParameter(
                name="submission_kind",
                type=str,
                location=OpenApiParameter.QUERY,
                description=(
                    "Filter by concrete submission model: "
                    "import, export, revenue_fine, health_inspection, destruction."
                ),
            )
        ],
    ),
    retrieve=extend_schema(tags=["Submissions"]),
    destroy=extend_schema(tags=["Submissions"]),
)
class SubmissionViewSet(
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
    viewsets.GenericViewSet,
):
    queryset = (
        Submission.objects.select_related(
            "submission_type",
            "checkpoint",
            "status",
            "created_by",
            "updated_by",
            "importsubmission__commodity_type__category",
            "importsubmission__unit_of_measurement",
            "exportsubmission__commodity_type__category",
            "exportsubmission__unit_of_measurement",
            "revenuefinesubmission__collection_type__category",
            "revenuefinesubmission__target_content_type",
            "healthinspectionsubmission__commodity_type__category",
            "healthinspectionsubmission__unit_of_measurement",
            "healthinspectionsubmission__target_content_type",
            "destructionsubmission__commodity_type__category",
            "destructionsubmission__unit_of_measurement",
            "destructionsubmission__target_content_type",
        )
        .prefetch_related(
            "documents__uploaded_by",
            "status_history__updated_by",
            "status_history__from_status",
            "status_history__to_status",
        )
        .all()
    )
    serializer_class = UnifiedSubmissionReadSerializer
    permission_classes = [permissions.IsAuthenticated]
    filterset_fields = (
        "submission_type",
        "status__code",
        "status__name",
        "checkpoint",
        "created_by",
        "nepali_year",
        "nepali_month",
        "nepali_quarter",
    )
    search_fields = ("tracking_code", "refrence_no", "remarks")
    ordering_fields = ("submitted_at", "created_at", "updated_at", "tracking_code", "nepali_year", "nepali_month")
    ordering = ("-created_at",)

    def get_queryset(self):
        queryset = super().get_queryset()
        current_user = self.request.user
        is_admin = is_admin_user(current_user)

        user_id = self.request.query_params.get("user")
        checkpoint_id = self.request.query_params.get("checkpoint")

        if not is_admin:
            user_checkpoint = getattr(current_user, "checkpoint", None)
            if not user_checkpoint:
                raise ValidationError(
                    {
                        "checkpoint": (
                            "No checkpoint is assigned to this user. "
                            "Please contact an administrator."
                        )
                    }
                )

            if checkpoint_id and str(checkpoint_id) != str(user_checkpoint.id):
                raise ValidationError(
                    {
                        "checkpoint": (
                            "You can only filter by your own assigned checkpoint."
                        )
                    }
                )

            if user_id:
                target_user = (
                    User.objects.filter(id=user_id, is_superuser=False)
                    .only("id", "checkpoint_id")
                    .first()
                )
                if not target_user:
                    raise ValidationError(
                        {"user": "A valid user with this exact UUID does not exist."}
                    )
                if target_user.checkpoint_id != user_checkpoint.id:
                    raise ValidationError(
                        {
                            "user": (
                                "You can only filter by users from your assigned "
                                "checkpoint."
                            )
                        }
                    )

            queryset = queryset.filter(checkpoint=user_checkpoint)

        if user_id:
            queryset = queryset.filter(created_by_id=user_id)
        if checkpoint_id:
            queryset = queryset.filter(checkpoint_id=checkpoint_id)

        submission_kind = self.request.query_params.get("submission_kind")
        if not submission_kind:
            return queryset

        relation_map = {
            "import": "importsubmission",
            "export": "exportsubmission",
            "revenue_fine": "revenuefinesubmission",
            "health_inspection": "healthinspectionsubmission",
            "destruction": "destructionsubmission",
        }
        relation_name = relation_map.get(submission_kind)
        if not relation_name:
            raise ValidationError(
                {
                    "submission_kind": (
                        "Invalid value. Use one of: "
                        "import, export, revenue_fine, health_inspection, destruction."
                    )
                }
            )

        return queryset.filter(**{f"{relation_name}__isnull": False})

    @extend_schema(
        tags=["Submissions"],
        request=SubmissionStatusChangeSerializer,
        responses={200: SubmissionStatusHistorySerializer},
        summary="Change Workflow Status",
        description="Allows an administrator to change the status of a submission and permanently log the workflow history."
    )
    @action(detail=True, methods=["post"], url_path="change-status", permission_classes=[IsAdminUserRole])
    def change_status(self, request, pk=None):
        submission = self.get_object()
        serializer = SubmissionStatusChangeSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        new_status = serializer.validated_data["status_id"]
        remarks = serializer.validated_data.get("remarks", "")
        old_status = submission.status

        if old_status == new_status:
            raise ValidationError({"status_id": "The submission is already in this status."})

        with transaction.atomic():
            # 1. Update parent submission
            submission.status = new_status
            submission.save(update_fields=["status", "updated_at"])

            # 2. Add permanent log
            history_log = SubmissionStatusHistory.objects.create(
                submission=submission,
                updated_by=request.user,
                from_status=old_status,
                to_status=new_status,
                remarks=remarks
            )

        response_serializer = SubmissionStatusHistorySerializer(history_log)
        return Response(response_serializer.data)


# ==========================================
# Primary Submission ViewSets
# ==========================================


@extend_schema_view(
    create=extend_schema(
        tags=["Import Submissions"],
        request=ImportSubmissionWriteSerializer,
        responses={201: ImportSubmissionReadSerializer},
    ),
    partial_update=extend_schema(
        tags=["Import Submissions"],
        request=ImportSubmissionWriteSerializer,
        responses={200: ImportSubmissionReadSerializer},
    ),
)
class ImportSubmissionViewSet(BaseSubmissionViewSet):
    queryset = ImportSubmission.objects.select_related(
        "submission_type",
        "checkpoint",
        "status",
        "created_by",
        "updated_by",
        "commodity_type__category",
        "unit_of_measurement",
    ).prefetch_related(
        "documents__uploaded_by",
        "status_history__updated_by",
        "status_history__from_status",
        "status_history__to_status",
    )
    read_serializer_class = ImportSubmissionReadSerializer
    write_serializer_class = ImportSubmissionWriteSerializer


@extend_schema_view(
    create=extend_schema(
        tags=["Export Submissions"],
        request=ExportSubmissionWriteSerializer,
        responses={201: ExportSubmissionReadSerializer},
    ),
    partial_update=extend_schema(
        tags=["Export Submissions"],
        request=ExportSubmissionWriteSerializer,
        responses={200: ExportSubmissionReadSerializer},
    ),
)
class ExportSubmissionViewSet(BaseSubmissionViewSet):
    queryset = ExportSubmission.objects.select_related(
        "submission_type",
        "checkpoint",
        "status",
        "created_by",
        "updated_by",
        "commodity_type__category",
        "unit_of_measurement",
    ).prefetch_related(
        "documents__uploaded_by",
        "status_history__updated_by",
        "status_history__from_status",
        "status_history__to_status",
    )
    read_serializer_class = ExportSubmissionReadSerializer
    write_serializer_class = ExportSubmissionWriteSerializer


@extend_schema_view(
    create=extend_schema(
        tags=["Revenue/Fine Submissions"],
        request=RevenueFineSubmissionWriteSerializer,
        responses={201: RevenueFineSubmissionReadSerializer},
    ),
    partial_update=extend_schema(
        tags=["Revenue/Fine Submissions"],
        request=RevenueFineSubmissionWriteSerializer,
        responses={200: RevenueFineSubmissionReadSerializer},
    ),
)
class RevenueFineSubmissionViewSet(BaseSubmissionViewSet):
    queryset = RevenueFineSubmission.objects.select_related(
        "submission_type",
        "checkpoint",
        "status",
        "created_by",
        "updated_by",
        "collection_type__category",
        "target_content_type",
    ).prefetch_related(
        "documents__uploaded_by",
        "status_history__updated_by",
        "status_history__from_status",
        "status_history__to_status",
    )
    read_serializer_class = RevenueFineSubmissionReadSerializer
    write_serializer_class = RevenueFineSubmissionWriteSerializer


@extend_schema_view(
    create=extend_schema(
        tags=["Health Inspection Submissions"],
        request=HealthInspectionSubmissionWriteSerializer,
        responses={201: HealthInspectionSubmissionReadSerializer},
    ),
    partial_update=extend_schema(
        tags=["Health Inspection Submissions"],
        request=HealthInspectionSubmissionWriteSerializer,
        responses={200: HealthInspectionSubmissionReadSerializer},
    ),
)
class HealthInspectionSubmissionViewSet(BaseSubmissionViewSet):
    queryset = HealthInspectionSubmission.objects.select_related(
        "submission_type",
        "checkpoint",
        "status",
        "created_by",
        "updated_by",
        "commodity_type__category",
        "unit_of_measurement",
        "target_content_type",
    ).prefetch_related(
        "documents__uploaded_by",
        "status_history__updated_by",
        "status_history__from_status",
        "status_history__to_status",
    )
    read_serializer_class = HealthInspectionSubmissionReadSerializer
    write_serializer_class = HealthInspectionSubmissionWriteSerializer


@extend_schema_view(
    create=extend_schema(
        tags=["Destruction Submissions"],
        request=DestructionSubmissionWriteSerializer,
        responses={201: DestructionSubmissionReadSerializer},
    ),
    partial_update=extend_schema(
        tags=["Destruction Submissions"],
        request=DestructionSubmissionWriteSerializer,
        responses={200: DestructionSubmissionReadSerializer},
    ),
)
class DestructionSubmissionViewSet(BaseSubmissionViewSet):
    queryset = DestructionSubmission.objects.select_related(
        "submission_type",
        "checkpoint",
        "status",
        "created_by",
        "updated_by",
        "commodity_type__category",
        "unit_of_measurement",
        "target_content_type",
    ).prefetch_related(
        "documents__uploaded_by",
        "status_history__updated_by",
        "status_history__from_status",
        "status_history__to_status",
    )
    read_serializer_class = DestructionSubmissionReadSerializer
    write_serializer_class = DestructionSubmissionWriteSerializer
