from rest_framework import serializers

from .services import BULK_FIXABLE_FIELDS


class IstatPeriodSerializer(serializers.Serializer):
    year = serializers.IntegerField(min_value=2000, max_value=2100)
    from_month = serializers.IntegerField(min_value=1, max_value=12)
    to_month = serializers.IntegerField(min_value=1, max_value=12)

    def validate(self, attrs):
        if attrs["from_month"] > attrs["to_month"]:
            raise serializers.ValidationError(
                "from_month cannot exceed to_month"
            )
        return attrs


class IstatPreviewRequestSerializer(serializers.Serializer):
    period = IstatPeriodSerializer()


class IstatCalendarRequestSerializer(serializers.Serializer):
    period = IstatPeriodSerializer()


class IstatExportRequestSerializer(serializers.Serializer):
    period = IstatPeriodSerializer()
    platform = serializers.ChoiceField(
        choices=[("ross1000_liguria", "Ross1000 Liguria")],
        required=False,
        default="ross1000_liguria",
    )


class IstatIssuesSummaryQuerySerializer(IstatPeriodSerializer):
    pass


class IstatMunicipalityQuerySerializer(serializers.Serializer):
    province = serializers.CharField(required=False, allow_blank=True)
    search = serializers.CharField(required=False, allow_blank=True)
    limit = serializers.IntegerField(required=False, min_value=1, max_value=100, default=25)


class IstatMunicipalityItemSerializer(serializers.Serializer):
    code = serializers.CharField()
    name = serializers.CharField()
    province = serializers.CharField()
    value = serializers.CharField()
    label = serializers.CharField()


class IstatMunicipalityResponseSerializer(serializers.Serializer):
    results = IstatMunicipalityItemSerializer(many=True)


class IstatFixIssueSerializer(serializers.Serializer):
    field = serializers.ChoiceField(choices=sorted(BULK_FIXABLE_FIELDS))
    value = serializers.CharField(trim_whitespace=True)
    guest_ids = serializers.ListField(
        child=serializers.IntegerField(min_value=1),
        allow_empty=False,
    )

    def validate_guest_ids(self, value):
        guest_ids = list(value)
        if len(guest_ids) != len(set(guest_ids)):
            raise serializers.ValidationError("guest_ids must be unique.")
        return guest_ids


class IstatFixIssuesRequestSerializer(serializers.Serializer):
    period = IstatPeriodSerializer()
    fixes = IstatFixIssueSerializer(many=True, allow_empty=False)

    def validate(self, attrs):
        seen_pairs = set()
        for fix in attrs["fixes"]:
            for guest_id in fix["guest_ids"]:
                key = (fix["field"], guest_id)
                if key in seen_pairs:
                    raise serializers.ValidationError(
                        {
                            "fixes": (
                                "Each guest can only appear once per field in a "
                                "bulk-fix request."
                            )
                        }
                    )
                seen_pairs.add(key)
        return attrs


class IstatIssueSummaryItemSerializer(serializers.Serializer):
    field = serializers.CharField()
    label = serializers.CharField()
    count = serializers.IntegerField()
    guest_ids = serializers.ListField(child=serializers.IntegerField())
    fix_type = serializers.CharField()
    options = serializers.ListField(
        child=serializers.CharField(),
        required=False,
    )
    suggested = serializers.CharField(required=False, allow_null=True)


class IstatIssuesSummaryResponseSerializer(serializers.Serializer):
    issues = IstatIssueSummaryItemSerializer(many=True)


class IstatFixIssuesResponseSerializer(serializers.Serializer):
    success = serializers.BooleanField()
    updated_count = serializers.IntegerField()
    remaining_issues = serializers.IntegerField()


class IstatCalendarDaySerializer(serializers.Serializer):
    date = serializers.DateField()
    day = serializers.IntegerField()
    available_rooms = serializers.IntegerField()
    available_beds = serializers.IntegerField()
    occupied_rooms = serializers.IntegerField()
    arrivals = serializers.IntegerField()
    departures = serializers.IntegerField()
    presences = serializers.IntegerField()
    status = serializers.CharField()


class IstatCalendarMonthSerializer(serializers.Serializer):
    year = serializers.IntegerField()
    month = serializers.IntegerField()
    label = serializers.CharField()
    total_rooms = serializers.IntegerField()
    total_beds = serializers.IntegerField()
    days = IstatCalendarDaySerializer(many=True)


class IstatCalendarResponseSerializer(serializers.Serializer):
    structure_id = serializers.IntegerField()
    structure_name = serializers.CharField()
    period = IstatPeriodSerializer()
    months = IstatCalendarMonthSerializer(many=True)
