from rest_framework import serializers

from companies.models import EmployeeSection, EmployeeSectionResponse, SectionField
from users.models import Company, CompanyUser


class CompanyCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('id', 'company_name', 'company_description', 'company_logo', 'date_created', 'last_updated')
        read_only_fields = ('id', 'date_created', 'last_updated')


class SectionFieldResponseUpdateSerializer(serializers.Serializer):
    section_field_id = serializers.IntegerField()
    response_value = serializers.CharField(allow_blank=True, allow_null=True, required=False)


class CompanyUserUpdateSerializer(serializers.ModelSerializer):
    section_field_responses = SectionFieldResponseUpdateSerializer(many=True, required=False)

    class Meta:
        model = CompanyUser
        fields = (
            'employment_number',
            'work_email_address',
            'phone_number',
            'profile_pic',
            'status',
            'start_date',
            'section_field_responses',
        )

    def validate_section_field_responses(self, value):
        company = self.context['company']
        seen = set()
        for item in value:
            section_field_id = item['section_field_id']
            if section_field_id in seen:
                raise serializers.ValidationError(
                    f'Duplicate section_field_id provided: {section_field_id}'
                )
            seen.add(section_field_id)

            exists_in_company = SectionField.objects.filter(
                id=section_field_id,
                employee_section__company=company,
                status=SectionField.Status.ACTIVE,
            ).exists()
            if not exists_in_company:
                raise serializers.ValidationError(
                    f'SectionField {section_field_id} does not exist for this company.'
                )

        return value

    def update(self, instance, validated_data):
        responses_data = validated_data.pop('section_field_responses', None)

        for attr, val in validated_data.items():
            setattr(instance, attr, val)
        instance.save()

        if responses_data is not None:
            for item in responses_data:
                section_field = SectionField.objects.get(
                    id=item['section_field_id'],
                    employee_section__company=instance.company,
                )

                EmployeeSectionResponse.objects.update_or_create(
                    user=instance.user,
                    company=instance.company,
                    section_field=section_field,
                    defaults={
                        'response_value': item.get('response_value', None),
                    },
                )

        return instance


class CompanyEmployeeReadSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    profile_pic = serializers.SerializerMethodField()
    section_response_groups = serializers.SerializerMethodField()

    class Meta:
        model = CompanyUser
        fields = (
            'id',
            'user',
            'company_id',
            'employment_number',
            'user_type',
            'work_email_address',
            'phone_number',
            'profile_pic',
            'status',
            'start_date',
            'section_response_groups',
        )

    def get_user(self, obj):
        return {
            'id': obj.user.id,
            'username': obj.user.username,
            'email': obj.user.email,
            'first_name': obj.user.first_name,
            'last_name': obj.user.last_name,
        }

    def get_profile_pic(self, obj):
        return str(obj.profile_pic) if obj.profile_pic else None

    def get_section_response_groups(self, obj):
        all_sections = EmployeeSection.objects.filter(company=obj.company).order_by('id')
        section_by_id = {section.id: section for section in all_sections}

        responses = EmployeeSectionResponse.objects.filter(
            company=obj.company,
            user=obj.user,
        ).select_related('section_field', 'section_field__employee_section')

        section_responses = {}
        involved_ids = set()

        for response in responses:
            section = response.section_field.employee_section
            section_responses.setdefault(section.id, []).append(
                {
                    'section_field_id': response.section_field.id,
                    'field_name': response.section_field.name,
                    'field_label': response.section_field.label,
                    'data_type': response.section_field.data_type,
                    'response_value': response.response_value,
                    'uploaded_file': str(response.uploaded_file) if response.uploaded_file else None,
                    'last_updated': response.last_updated,
                }
            )
            involved_ids.add(section.id)

        # Include all ancestors for proper section nesting.
        for section_id in list(involved_ids):
            current = section_by_id.get(section_id)
            while current and current.parent_id_id:
                parent_id = current.parent_id_id
                involved_ids.add(parent_id)
                current = section_by_id.get(parent_id)

        nodes = {}
        for section_id in involved_ids:
            section = section_by_id.get(section_id)
            if not section:
                continue
            nodes[section_id] = {
                'id': section.id,
                'name': section.name,
                'section_class': section.section_class,
                'parent_id': section.parent_id_id,
                'responses': section_responses.get(section.id, []),
                'children': [],
            }

        roots = []
        for node in nodes.values():
            parent_id = node['parent_id']
            if parent_id and parent_id in nodes:
                nodes[parent_id]['children'].append(node)
            else:
                roots.append(node)

        for node in nodes.values():
            node['children'].sort(key=lambda item: item['name'])

        grouped = {
            EmployeeSection.SectionClass.PERSONAL: [],
            EmployeeSection.SectionClass.EMPLOYMENT: [],
        }
        for root in sorted(roots, key=lambda item: item['name']):
            grouped[root['section_class']].append(root)

        return [
            {
                'section_class': EmployeeSection.SectionClass.PERSONAL,
                'sections': grouped[EmployeeSection.SectionClass.PERSONAL],
            },
            {
                'section_class': EmployeeSection.SectionClass.EMPLOYMENT,
                'sections': grouped[EmployeeSection.SectionClass.EMPLOYMENT],
            },
        ]


class TerminateEmployeeItemSerializer(serializers.Serializer):
    user_id = serializers.IntegerField(min_value=1)
    company_id = serializers.IntegerField(min_value=1)


class TerminateEmployeesBulkSerializer(serializers.Serializer):
    employees = TerminateEmployeeItemSerializer(many=True)


class InviteEmployeeItemSerializer(serializers.Serializer):
    first_name = serializers.CharField(max_length=150)
    last_name = serializers.CharField(max_length=150)
    email = serializers.EmailField()
    job_title = serializers.CharField(max_length=255)


class InviteEmployeesBulkSerializer(serializers.Serializer):
    employees = InviteEmployeeItemSerializer(many=True)
