from rest_framework.serializers import ModelSerializer
from rest_framework import serializers

from django.contrib.auth.hashers import make_password
from django.db.models import Q

from decimal import Decimal

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

from apps.user.models import User
from apps.employee.models import Activity
from apps.project.models import Project



class EmployeeCreateAPISerializer(ModelSerializer):
    password = serializers.CharField(write_only=True)
    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'phone_no', 'email', "password", 'pay_per_hour', 'position', 'is_active',)
        extra_kwargs = {
            'first_name': {'required': True},
            'last_name': {'required': True},
            'email': {'required': True},
            'phone_no': {'required': True},
            "password": {'required': True},
            "is_active": {'required': True},
        }

    def validate(self, attrs):
        email = attrs.get('email')
        phone_no = attrs.get('phone_no')

        users = User.objects.filter(Q(email=email) | Q(phone_no=phone_no))

        if users.exists():
            existing_user = users.first()
            if existing_user.email == email:
                raise serializers.ValidationError("A user with this email already exists.")
            else:
                raise serializers.ValidationError("A user with this phone number already exists.")

        attrs['password'] = make_password(attrs['password'])

        return super().validate(attrs)


class EmployeeAssignProjectSerializer(serializers.Serializer):
    project_id = serializers.ListField(child=serializers.IntegerField())

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

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

        return value


class EmployeeUpdateAPISerializer(ModelSerializer):
    password = serializers.CharField(required=False, allow_null=True, write_only=True, allow_blank=True)

    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'phone_no', 'email', 'password', 'pay_per_hour', 'position', 'is_active',)
        extra_kwargs = {
            'first_name': {'required': True},
            'last_name': {'required': True},
            'email': {'required': True},
            'phone_no': {'required': True},
            'is_active': {'required': True},
        }

    def validate(self, attrs):
        if 'password' in attrs:
            password = attrs.get('password')

            if password is None or password == '':
                attrs.pop('password')
            else:
                attrs['password'] = make_password(attrs['password'])

        email = attrs.get('email')
        phone_no = attrs.get('phone_no')
        instance = self.instance

        users = User.objects.filter(Q(email=email) | Q(phone_no=phone_no))

        if instance:
            users = users.exclude(id=instance.id)

        if users.exists():
            if users.filter(email=email).exists():
                raise serializers.ValidationError("A user with this email already exists.")
            if users.filter(phone_no=phone_no).exists():
                raise serializers.ValidationError("A user with this phone number already exists.")

        return attrs


class EmployeeListAPISerializer(ModelSerializer):
    total_working_duration = serializers.DurationField(allow_null=True)
    full_name = serializers.CharField(allow_null=True)
    total_amount = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id', 'full_name', 'phone_no', 'email', "profile_pic", 'position', 'pay_per_hour', 'total_working_duration', 'total_amount','deleted_at', 'is_active',)
        read_only_fields = fields

    def get_total_amount(self, instance):
        project_id = self.context['request'].query_params.get('project_id', None)
        activities = instance.activity_set.all()
        if project_id:
            activities = activities.filter(project_id=project_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)
        formatted_total_amount =format_amount_with_currency(total_amount)
        return formatted_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 EmployeeDeleteAPISerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name')


class ProjectEmployeeDetailSerializer(serializers.ModelSerializer):
    client_name = serializers.ReadOnlyField(source='client.name')

    class Meta:
        model = Project
        fields = ('id', 'name', 'client', 'client_name',)


class EmployeeDetailAPISerializer(ModelSerializer):
    projects= ProjectEmployeeDetailSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'email', 'phone_no', 'profile_pic', 'pay_per_hour', 'projects', 'position', 'is_active', 'deleted_at',)
        read_only_fields = fields


class CurrentActivitySerializer(ModelSerializer):
    project_name = serializers.CharField(source='project.name')
    activity_type = serializers.CharField(source='activity_type.name')

    class Meta:
        model = Activity
        fields = ('id', 'project_id', 'project_name', 'activity_type_id', 'activity_type', 'start_date_time', 'end_date_time', 'total_duration', 'description',)
