from rest_framework import serializers
from rest_framework.serializers import ModelSerializer, ValidationError

from core.utils.helper import timedelta_to_custom_format, duration_string_to_timedelta, format_amount_with_currency

from apps.project.models import Project
from apps.vendor.models import Vendor, VendorType
from apps.consultant.models import Consultant
from apps.contractor.models import Contractor



class ProjectListSerializer(ModelSerializer):
    client_name = serializers.ReadOnlyField()
    total_vendors = serializers.IntegerField()
    total_consultants = serializers.IntegerField()
    total_contractors = serializers.IntegerField()
    total_working_duration = serializers.DurationField(allow_null=True)
    total_amount = serializers.SerializerMethodField()


    class Meta:
        model = Project
        fields = ('id', 'name', 'client_name','total_vendors', 'total_consultants', 'total_contractors', 'total_working_duration', 'deleted_at', 'total_amount',)
        read_only_fields = fields

    def get_total_amount(self, instance):
        """
        Calculate the total cost for the project by summing
        (duration in hours * pay_per_hour) across all activities.
        """
        employee_id = self.context['request'].query_params.get('employee_id', None)

        activities = instance.activity_set.all()

        if employee_id:
            activities = activities.filter(user_id=employee_id)

        total_amount = sum((activity.total_duration.total_seconds() / 3600) * activity.pay_per_hour if activity.total_duration and activity.pay_per_hour else 0 for activity in activities)
        return format_amount_with_currency(total_amount)


    def to_representation(self, instance):
        res = super().to_representation(instance)
        res['total_working_duration'] = timedelta_to_custom_format(duration_string_to_timedelta(res['total_working_duration']))

        return res


class ProjectAddSerializer(ModelSerializer):
    budget = serializers.FloatField(required=False, allow_null=True)
    description = serializers.CharField(allow_null=True, required=False)
    name = serializers.CharField()
    address = serializers.CharField(required=False, allow_null=True)

    class Meta:
        model = Project
        fields = ('id', 'name', 'client', 'address', 'note', 'budget', 'description',)

    def to_internal_value(self, data):
        if data.get('budget', None) == '':
            data.pop('budget')
        return super(ProjectAddSerializer, self).to_internal_value(data)

    def validate_name(self, value):
        project_id = self.context.get('project_id')
        if Project.objects.exclude(id=project_id).filter(name=value).exists():
            raise ValidationError("A project with this name already exists.")
        return value


class VendorListSerializer(ModelSerializer):
    type = serializers.CharField(source='type.name')

    class Meta:
        model = Vendor
        fields = ('id', 'name', 'type', 'phone_no',)
        read_only_fields = fields


class VendorSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source='type.name', allow_null=True,)
    added_by = serializers.CharField(source='get_full_name', read_only=True)

    class Meta:
        model = Vendor
        fields = ('id', 'name', 'type', 'phone_no', 'added_by',)


class ConsultantListSerializer(ModelSerializer):
    type = serializers.CharField(source='type.name')

    class Meta:
        model = Consultant
        fields = ('id', 'name', 'type', 'phone_no',)
        read_only_fields = fields


class ConsultantSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source='type.name', allow_null=True,)
    added_by = serializers.CharField(source='get_created_by_full_name', read_only=True)

    class Meta:
        model = Consultant
        fields = ('id', 'name', 'type', 'phone_no', 'added_by',)


class ContractorListSerializer(ModelSerializer):
    type = serializers.CharField(source='type.name')

    class Meta:
        model = Contractor
        fields = ('id', 'name', 'type', 'phone_no',)
        read_only_fields = fields


class ContractorSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source='type.name', allow_null=True,)
    added_by = serializers.CharField(source='get_created_by_full_name', read_only=True)

    class Meta:
        model = Contractor
        fields = ('id', 'name', 'type', 'phone_no', 'added_by',)


class ProjectDetailSerializer(serializers.ModelSerializer):
    client_name = serializers.ReadOnlyField(source='client.name')
    client_phone_no = serializers.ReadOnlyField(source='client.phone_no')
    client_address = serializers.ReadOnlyField(source='client.address')
    description = serializers.CharField(allow_null=True, required=False)

    class Meta:
        model = Project
        fields = ('id', 'name', 'client', 'client_name', 'client_phone_no', 'client_address', 'address', 'note', 'budget', 'description', 'deleted_at', 'minutes_of_meeting',)


class ProjectMinutesOfMeetingSerializer(ModelSerializer):
    class Meta:
        model = Project
        fields = ('minutes_of_meeting',)



class ProjectDeleteAPISerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = ('id', 'name', 'client', 'address', 'note', 'budget', 'description',)


class ProjectConsultantSerializer(serializers.Serializer):
    consultant_id = serializers.ListField(child=serializers.IntegerField())

    def validate_consultant_id(self, value):
        if not value:
            raise serializers.ValidationError("At least one consultant ID must be provided.")

        for consultant_id in value:
            if not isinstance(consultant_id, int) or consultant_id <= 0:
                raise serializers.ValidationError("Invalid consultant ID: {}".format(consultant_id))

        return value

class ProjectContractorSerializer(serializers.Serializer):
    contractor_id = serializers.ListField(child=serializers.IntegerField())

    def validate_contractor_id(self, value):
        if not value:
            raise serializers.ValidationError("At least one contractor ID must be provided.")

        for contractor_id in value:
            if not isinstance(contractor_id, int) or contractor_id <= 0:
                raise serializers.ValidationError("Invalid contractor ID: {}".format(contractor_id))

        return value

class ProjectVendorSerializer(serializers.Serializer):
    vendor_id = serializers.ListField(child=serializers.IntegerField())

    def validate_vendor_id(self, value):
        if not value:
            raise serializers.ValidationError("At least one vendor ID must be provided.")

        for vendor_id in value:
            if not isinstance(vendor_id, int) or vendor_id <= 0:
                raise serializers.ValidationError("Invalid vendor ID: {}".format(vendor_id))

        return value


class ProjectAssignEmployeeAPISerializer(serializers.Serializer):
    employee_ids = serializers.ListField(child=serializers.IntegerField())

    def validate_employee_ids(self, value):
        if not value:
            raise serializers.ValidationError("At least one employee ID must be provided.")

        for employee_id in value:
            if not isinstance(employee_id, int) or employee_id <= 0:
                raise serializers.ValidationError("Invalid Employee ID: {}".format(employee_id))

        return value

