import datetime

from rest_framework import serializers

from apps.account import models
from apps.master.serializers.master_serializers import ConnectorMasterSerializers
from apps.vehicle.serializers.vehicle_serializers import (
    VehicleMakeMasterSerializers,
    VehicleModelMasterSerializers,
)
from base.serializers import DynamicFieldsModelSerializer


class UserVehicleAssetSerializer(DynamicFieldsModelSerializer):
    """
    Serializer class for serializing and deserializing UserVehicleAssets instances.

    This serializer class includes fields for 'id', 'user_vehicle', and 'asset'.
    'id' and 'user_vehicle' are marked as read-only.

    Attributes:
        Meta.model: The model class to which this serializer applies.
        Meta.fields: The fields to include in the serialized representation.
        Meta.read_only_fields: The fields that should be treated as read-only during updates.
    """

    class Meta:
        model = models.UserVehicleAssets
        fields = (
            "id",
            "user_vehicle",
            "asset",
        )
        read_only_fields = ["id", "user_vehicle"]


class UserVehicleSerializer(DynamicFieldsModelSerializer):
    """
    This serializer is used for validating and deserializing user vehicle data and user profile updates.

    Fields:
        vehicle_make (str): The make of the user's vehicle.
        vehicle_model (str): The model of the user's vehicle.
        connector (str): The connector type of the user's vehicle.
        wheeler_type (str): The type of vehicle (e.g., two-wheeler, four-wheeler, etc.).
        manufacturing_year (int): The manufacturing year of the vehicle.
        vehicle_number (str): The vehicle registration number.
        asset (File): An optional asset (e.g., an image) associated with the vehicle.

    These fields are required and should not be blank or null.

    Inherits from DynamicFieldsModelSerializer to provide flexibility in specifying fields.

    Meta:
        model (UserVehicle): The model used for serialization and deserialization.
        fields (str): The fields to include in the serialization.
        read_only_fields (str): The fields that are read-only.

    Methods:
        update(instance, validated_data): Updates the user vehicle record, validating and saving changes.
    """

    vehicle_make_data = VehicleMakeMasterSerializers(
        source="vehicle_make", read_only=True, fields=["id", "name"]
    )
    vehicle_model_data = VehicleModelMasterSerializers(
        source="vehicle_model", read_only=True, fields=["id", "name"]
    )
    connector_data = ConnectorMasterSerializers(
        source="connector", read_only=True, fields=["id", "name"]
    )

    media = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = models.UserVehicle
        fields = (
            "id",
            "vehicle_make",
            "vehicle_model",
            "connector",
            "manufacturing_year",
            "vehicle_number",
            "vehicle_make_data",
            "vehicle_model_data",
            "connector_data",
            "media",
        )
        read_only_fields = (
            "id",
            "connector_data",
        )
        extra_kwargs = {
            "vehicle_make": {"write_only": True},
            "vehicle_model": {"write_only": True},
            "connector": {"write_only": True},
        }

    def validate_manufacturing_year(self, value):
        """
        Validate manufacturing year.
        """
        current_year = datetime.date.today().year
        min_year = 1984

        if not min_year <= value <= current_year:
            raise serializers.ValidationError(
                f"Manufacturing year should be between {min_year} and {current_year}."
            )

        return value

    def get_media(self, obj):
        """
        Retrieve and format associated media assets.

        Args:
            obj: The station rating record.

        Returns:
            List of dictionaries with media asset details.
        """
        medias = obj.user_vehicle_assets.all()
        media_data = []

        for media in medias:
            if media.asset:
                media_item = {
                    "id": media.id,
                    "asset": self.context["request"].build_absolute_uri(
                        media.asset.url
                    ),
                }
                media_data.append(media_item)

        return media_data

    def update(self, instance, validated_data):
        """
        Update the user vehicle record, validating and saving changes.

        Args:
        instance (UserVehicle): The existing user vehicle record.
        validated_data (dict): Validated data containing updated vehicle details.

        Returns:
        UserVehicle: The updated user vehicle record.

        This method updates the user vehicle record, with validation checks to ensure that the user has
        permission to update the record.
        """
        request = self.context.get("request")
        if instance.user != request.user:
            raise serializers.ValidationError(
                "You have no permission to update this vehicle"
            )
        instance = super(UserVehicleSerializer, self).update(instance, validated_data)
        return instance
