from rest_framework import serializers
from payroll.models import (
    PayrollIntegration,
    EmployeeMapping,
    ProjectMapping,
    PayrollSubmission,
    PayrollSubmissionStamp
)
from user.models import User
from projects.models import Project


class PayrollIntegrationSerializer(serializers.ModelSerializer):
    company_name = serializers.SerializerMethodField()
    
    class Meta:
        model = PayrollIntegration
        fields = [
            'id', 'company_name', 'provider', 'is_active',
            'api_endpoint', 'api_key', 'api_secret', 'last_sync',
            'sync_frequency', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'last_sync']
        # Explicitly exclude 'company' field to prevent DRF from trying to serialize it
        exclude = []
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Remove 'company' field if it was auto-created by DRF
        if 'company' in self.fields:
            del self.fields['company']
    
    def get_company_name(self, obj):
        """Get company name safely without accessing relationship"""
        try:
            if not obj.company_id:
                return None
            # Query company directly by ID to avoid relationship issues
            from company.models import Company
            company = Company.objects.filter(id=obj.company_id).only('name').first()
            return company.name if company else None
        except Exception:
            return None
    
    def to_representation(self, instance):
        """Override to ensure UUID fields are serialized as strings and add company field manually"""
        # Build representation manually to completely avoid DRF's automatic field handling
        representation = {
            'id': str(instance.id),
            'company': str(instance.company_id) if instance.company_id else None,
            'company_name': self.get_company_name(instance),
            'provider': instance.provider,
            'is_active': instance.is_active,
            'api_endpoint': instance.api_endpoint,
            'api_key': instance.api_key,
            'api_secret': instance.api_secret,
            'last_sync': instance.last_sync,
            'sync_frequency': instance.sync_frequency,
            'created_at': instance.created_at,
            'updated_at': instance.updated_at,
        }
        return representation
    
    def validate(self, data):
        """Validate that API credentials are provided when active"""
        if data.get('is_active') and data.get('provider') != 'none':
            if not data.get('api_endpoint'):
                raise serializers.ValidationError("API endpoint is required when integration is active")
            if not data.get('api_key'):
                raise serializers.ValidationError("API key is required when integration is active")
        return data
    
    def create(self, validated_data):
        """Override create to set company from request context"""
        # Get company from request data or context
        company_id = self.context.get('request').data.get('company')
        if not company_id:
            # Try to get from validated_data if it was passed
            company_id = validated_data.pop('company', None)
        
        if not company_id:
            raise serializers.ValidationError({
                'company': 'Company is required. Please provide company ID.'
            })
        
        # Import here to avoid circular imports
        from company.models import Company
        try:
            company = Company.objects.get(id=company_id)
        except Company.DoesNotExist:
            raise serializers.ValidationError({
                'company': 'Company not found.'
            })
        
        # Set company in validated_data
        validated_data['company'] = company
        return super().create(validated_data)
    
    def update(self, instance, validated_data):
        """Override update to handle company if provided"""
        company_id = self.context.get('request').data.get('company')
        if company_id:
            from company.models import Company
            try:
                company = Company.objects.get(id=company_id)
                validated_data['company'] = company
            except Company.DoesNotExist:
                raise serializers.ValidationError({
                    'company': 'Company not found.'
                })
        
        return super().update(instance, validated_data)


class EmployeeMappingSerializer(serializers.ModelSerializer):
    user_name = serializers.SerializerMethodField()
    user_email = serializers.EmailField(source='user.email', read_only=True)
    
    class Meta:
        model = EmployeeMapping
        fields = [
            'id', 'user', 'user_name', 'user_email', 'payroll_integration',
            'external_employee_id', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']
        extra_kwargs = {
            'user': {'required': True},
            'payroll_integration': {'required': True}
        }
    
    def get_user_name(self, obj):
        return f"{obj.user.firstname} {obj.user.lastname}"


class ProjectMappingSerializer(serializers.ModelSerializer):
    project_name = serializers.CharField(source='project.name', read_only=True)
    project_code = serializers.CharField(source='project.code', read_only=True)
    
    class Meta:
        model = ProjectMapping
        fields = [
            'id', 'project', 'project_name', 'project_code', 'payroll_integration',
            'external_project_code', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']
        extra_kwargs = {
            'project': {'required': True},
            'payroll_integration': {'required': True}
        }


class PayrollSubmissionStampSerializer(serializers.ModelSerializer):
    stamp_date = serializers.DateField(source='stamp.date', read_only=True)
    stamp_time = serializers.TimeField(source='stamp.time', read_only=True)
    stamp_description = serializers.CharField(source='stamp.description', read_only=True)
    
    class Meta:
        model = PayrollSubmissionStamp
        fields = ['id', 'stamp', 'stamp_date', 'stamp_time', 'stamp_description', 'created_at']
        read_only_fields = ['id', 'created_at']


class PayrollSubmissionSerializer(serializers.ModelSerializer):
    user_name = serializers.SerializerMethodField()
    user_email = serializers.EmailField(source='user.email', read_only=True)
    provider_name = serializers.CharField(source='payroll_integration.get_provider_display', read_only=True)
    stamps = PayrollSubmissionStampSerializer(source='submission_stamps', many=True, read_only=True)
    
    class Meta:
        model = PayrollSubmission
        fields = [
            'id', 'payroll_integration', 'provider_name', 'user', 'user_name', 'user_email',
            'period_start', 'period_end', 'submission_status', 'external_reference_id',
            'submitted_at', 'error_message', 'stamps', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'submitted_at']
    
    def get_user_name(self, obj):
        return f"{obj.user.firstname} {obj.user.lastname}"


class PayrollSubmitRequestSerializer(serializers.Serializer):
    """Serializer for timesheet submission request"""
    user_id = serializers.UUIDField()
    period_start = serializers.DateField()
    period_end = serializers.DateField()
    stamp_ids = serializers.ListField(
        child=serializers.UUIDField(),
        required=False,
        allow_empty=True
    )
    
    def validate(self, data):
        if data['period_start'] > data['period_end']:
            raise serializers.ValidationError("period_start must be before period_end")
        return data

