from rest_framework import serializers
from .models import Stamp
from functions.models import Function

class StampSerializer(serializers.ModelSerializer):
    user_id = serializers.UUIDField(write_only=True)
    project_id = serializers.UUIDField(write_only=True, required=False, allow_null=True)
    task_id = serializers.UUIDField(write_only=True, required=False, allow_null=True)
    hours = serializers.CharField(write_only=True, required=False, allow_null=True, allow_blank=True)
    function_name = serializers.SerializerMethodField()
    function_icon = serializers.SerializerMethodField()
    function_color = serializers.SerializerMethodField()
    project_name = serializers.SerializerMethodField()
    task_name = serializers.SerializerMethodField()

    class Meta:
        model = Stamp
        fields = [
            'id', 'user_id', 'stamp_function', 'function_name', 'function_icon', 'function_color', 'description',
            'time', 'date', 'start_date', 'return_date', 'work_id', 'status',
            'project', 'project_id', 'project_name', 'task', 'task_id', 'task_name',
            'duration', 'hours', 'paycode', 'source',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'function_name', 'function_icon', 'function_color', 'project_name', 'task_name']

    def get_function_name(self, obj):
        """Get function name from context"""
        functions_dict = self.context.get('functions_dict', {})
        func_data = functions_dict.get(obj.stamp_function)
        if isinstance(func_data, dict):
            return func_data.get('header')
        elif func_data is None:
            return None
        # Handle old format where it was just a string
        return func_data
    
    def get_function_icon(self, obj):
        """Get function icon from context - return exactly as defined in configuration (matching monthly_balance endpoint)"""
        functions_dict = self.context.get('functions_dict', {})
        func_data = functions_dict.get(obj.stamp_function)
        if isinstance(func_data, dict):
            # Get icon exactly as defined in configuration (including empty strings)
            # Default to empty string if key missing (matching monthly_balance endpoint)
            function_icon = func_data.get('icon', '')
            return function_icon  # Return exactly as stored (could be empty string or actual value)
        else:
            # Return empty string if config doesn't exist (matching monthly_balance endpoint)
            return ''
    
    def get_function_color(self, obj):
        """Get function color from context - return exactly as defined in configuration (matching monthly_balance endpoint)"""
        functions_dict = self.context.get('functions_dict', {})
        func_data = functions_dict.get(obj.stamp_function)
        if isinstance(func_data, dict):
            # Get color exactly as defined in configuration (including empty strings)
            # Default to empty string if key missing (matching monthly_balance endpoint)
            function_color = func_data.get('color', '')
            return function_color  # Return exactly as stored (could be empty string or actual value)
        else:
            # Return empty string if config doesn't exist (matching monthly_balance endpoint)
            return ''

    def get_project_name(self, obj):
        """Get project name"""
        return obj.project.name if obj.project else None

    def get_task_name(self, obj):
        """Get task name"""
        return obj.task.name if obj.task else None

    def validate_user_id(self, value):
        from user.models import User
        try:
            User.objects.get(id=value)
        except User.DoesNotExist:
            raise serializers.ValidationError("User does not exist")
        return value

    def validate_project_id(self, value):
        # Convert empty string to None
        if value == '' or value is None:
            return None
        return value

    def validate_task_id(self, value):
        # Convert empty string to None
        if value == '' or value is None:
            return None
        return value

    def to_internal_value(self, data):
        # Convert empty strings to None for UUID fields before validation
        if 'project_id' in data and data['project_id'] == '':
            data['project_id'] = None
        if 'task_id' in data and data['task_id'] == '':
            data['task_id'] = None
        return super().to_internal_value(data)

    def validate(self, data):
        if data.get('return_date') and data.get('start_date'):
            from django.utils.dateparse import parse_datetime
            from django.utils import timezone
            
            start_date = data['start_date']
            return_date = data['return_date']
            
            if isinstance(start_date, str):
                start_date = parse_datetime(start_date) or timezone.now()
            if isinstance(return_date, str):
                return_date = parse_datetime(return_date) or timezone.now()
            
            if timezone.is_naive(start_date):
                start_date = timezone.make_aware(start_date)
            if timezone.is_naive(return_date):
                return_date = timezone.make_aware(return_date)
            
            # Compare only the date part (ignore time) to allow same-day return dates
            start_date_only = start_date.date()
            return_date_only = return_date.date()
            
            if return_date_only < start_date_only:
                raise serializers.ValidationError("Return date cannot be before start date")
        return data

    def create(self, validated_data):
        from user.models import User
        from projects.models import Project
        from tasks.models import Task
        
        user_id = validated_data.pop('user_id')
        project_id = validated_data.pop('project_id', None)
        task_id = validated_data.pop('task_id', None)
        hours = validated_data.pop('hours', None)
        
        user = User.objects.get(id=user_id)
        
        # Map project_id to project
        project = None
        if project_id:
            try:
                project = Project.objects.get(id=project_id)
            except Project.DoesNotExist:
                pass
        
        # Map task_id to task
        task = None
        if task_id:
            try:
                task = Task.objects.get(id=task_id)
            except Task.DoesNotExist:
                pass
        
        # Map hours to duration
        if hours:
            validated_data['duration'] = hours
        
        return Stamp.objects.create(
            user=user,
            project=project,
            task=task,
            **validated_data
        )

    def update(self, instance, validated_data):
        from projects.models import Project
        from tasks.models import Task
        
        project_id = validated_data.pop('project_id', None)
        task_id = validated_data.pop('task_id', None)
        hours = validated_data.pop('hours', None)
        
        # Map project_id to project
        if project_id is not None:
            try:
                instance.project = Project.objects.get(id=project_id) if project_id else None
            except Project.DoesNotExist:
                instance.project = None
        
        # Map task_id to task
        if task_id is not None:
            try:
                instance.task = Task.objects.get(id=task_id) if task_id else None
            except Task.DoesNotExist:
                instance.task = None
        
        # Map hours to duration
        if hours is not None:
            instance.duration = hours if hours else None
        
        # Update other fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        
        instance.save()
        return instance 