"""
External API serializers for public-facing create/retrieve operations.
"""

from rest_framework import serializers

from apps.complaints.models import Complaint, Inquiry
from apps.observations.models import Observation
from apps.appreciation.models import Appreciation, AppreciationStatus, AppreciationVisibility
from apps.feedback.models import Feedback, FeedbackType, FeedbackStatus, FeedbackCategory


# ---------------------------------------------------------------------------
# Complaint
# ---------------------------------------------------------------------------

class ExternalComplaintCreateSerializer(serializers.Serializer):
    """Public-facing fields for creating a complaint via external API."""

    # Contact
    contact_name = serializers.CharField(max_length=200, required=True)
    contact_phone = serializers.CharField(max_length=20, required=True)
    contact_email = serializers.EmailField(required=False, allow_blank=True, default="")
    relation_to_patient = serializers.ChoiceField(
        choices=[("patient", "Patient"), ("relative", "Relative"), ("friend", "Friend"), ("other", "Other")],
        required=False,
        allow_blank=True,
        default="",
    )

    # Patient
    patient_name = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    national_id = serializers.CharField(max_length=50, required=False, allow_blank=True, default="")
    incident_date = serializers.DateField(required=False, allow_null=True, default=None)

    # Hospital context
    hospital = serializers.CharField(max_length=200, required=True)

    # Location hierarchy (all optional)
    location_type = serializers.ChoiceField(
        choices=[("OP", "Outpatient"), ("IP", "Inpatient"), ("ER", "Emergency"), ("GENERAL", "General")],
        required=False,
        allow_blank=True,
        default="",
    )
    area = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    department = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    section = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")

    # Complaint content
    title = serializers.CharField(max_length=500, required=True)
    description = serializers.CharField(required=True)
    expected_result = serializers.CharField(required=False, allow_blank=True, default="")

    def validate_hospital(self, value):
        from apps.organizations.models import Hospital
        try:
            return Hospital.objects.get(name__iexact=value.strip())
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")

    def validate(self, data):
        hospital = data.get("hospital")
        if hospital:
            area_name = data.get("area")
            if area_name:
                from apps.organizations.models import Area
                try:
                    data["area"] = Area.objects.get(
                        name_en__iexact=area_name.strip(), hospital=hospital, status="active"
                    )
                except Area.DoesNotExist:
                    raise serializers.ValidationError({"area": f"Area '{area_name}' not found for this hospital."})

            dept_name = data.get("department")
            if dept_name:
                from apps.organizations.models import Department
                try:
                    data["department"] = Department.objects.get(
                        name__iexact=dept_name.strip(), hospital=hospital, status="active"
                    )
                except Department.DoesNotExist:
                    raise serializers.ValidationError(
                        {"department": f"Department '{dept_name}' not found for this hospital."}
                    )

            section_name = data.get("section")
            if section_name:
                department = data.get("department")
                if not department:
                    raise serializers.ValidationError({"section": "Department is required to look up section."})
                from apps.organizations.models import Section
                try:
                    data["section"] = Section.objects.get(
                        name_en__iexact=section_name.strip(), department=department, status="active"
                    )
                except Section.DoesNotExist:
                    raise serializers.ValidationError(
                        {"section": f"Section '{section_name}' not found for this department."}
                    )

        return data


class ExternalComplaintRetrieveSerializer(serializers.ModelSerializer):
    """Read-only serializer for retrieving a complaint."""

    hospital_name = serializers.CharField(source="hospital.name", read_only=True)

    class Meta:
        model = Complaint
        fields = [
            "id",
            "reference_number",
            "title",
            "description",
            "status",
            "severity",
            "priority",
            "contact_name",
            "contact_phone",
            "contact_email",
            "relation_to_patient",
            "patient_name",
            "incident_date",
            "expected_result",
            "resolution",
            "satisfaction",
            "hospital_name",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields


# ---------------------------------------------------------------------------
# Inquiry
# ---------------------------------------------------------------------------

class ExternalInquiryCreateSerializer(serializers.Serializer):
    """Public-facing fields for creating an inquiry via external API."""

    # Contact
    contact_name = serializers.CharField(max_length=200, required=True)
    contact_phone = serializers.CharField(max_length=20, required=True)
    contact_email = serializers.EmailField(required=False, allow_blank=True, default="")

    # Hospital context
    hospital = serializers.CharField(max_length=200, required=True)

    # Location hierarchy (all optional)
    location_type = serializers.ChoiceField(
        choices=[("OP", "Outpatient"), ("IP", "Inpatient"), ("ER", "Emergency"), ("GENERAL", "General")],
        required=False,
        allow_blank=True,
        default="",
    )
    area = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    department = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    section = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")

    # Inquiry content
    subject = serializers.CharField(max_length=500, required=True)
    message = serializers.CharField(required=True)
    category = serializers.ChoiceField(
        choices=[
            ("appointment", "Appointment"),
            ("billing", "Billing"),
            ("medical_records", "Medical Records"),
            ("general", "General Information"),
            ("other", "Other"),
        ],
        required=False,
        default="general",
    )

    def validate_hospital(self, value):
        from apps.organizations.models import Hospital
        try:
            return Hospital.objects.get(name__iexact=value.strip())
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")

    def validate(self, data):
        hospital = data.get("hospital")
        if hospital:
            area_name = data.get("area")
            if area_name:
                from apps.organizations.models import Area
                try:
                    data["area"] = Area.objects.get(
                        name_en__iexact=area_name.strip(), hospital=hospital, status="active"
                    )
                except Area.DoesNotExist:
                    raise serializers.ValidationError({"area": f"Area '{area_name}' not found for this hospital."})

            dept_name = data.get("department")
            if dept_name:
                from apps.organizations.models import Department
                try:
                    data["department"] = Department.objects.get(
                        name__iexact=dept_name.strip(), hospital=hospital, status="active"
                    )
                except Department.DoesNotExist:
                    raise serializers.ValidationError(
                        {"department": f"Department '{dept_name}' not found for this hospital."}
                    )

            section_name = data.get("section")
            if section_name:
                department = data.get("department")
                if not department:
                    raise serializers.ValidationError({"section": "Department is required to look up section."})
                from apps.organizations.models import Section
                try:
                    data["section"] = Section.objects.get(
                        name_en__iexact=section_name.strip(), department=department, status="active"
                    )
                except Section.DoesNotExist:
                    raise serializers.ValidationError(
                        {"section": f"Section '{section_name}' not found for this department."}
                    )

        return data


class ExternalInquiryRetrieveSerializer(serializers.ModelSerializer):
    """Read-only serializer for retrieving an inquiry."""

    hospital_name = serializers.CharField(source="hospital.name", read_only=True)

    class Meta:
        model = Inquiry
        fields = [
            "id",
            "reference_number",
            "subject",
            "message",
            "category",
            "status",
            "contact_name",
            "contact_phone",
            "contact_email",
            "hospital_name",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields


# ---------------------------------------------------------------------------
# Observation
# ---------------------------------------------------------------------------

class ExternalObservationCreateSerializer(serializers.Serializer):
    """Public-facing fields for creating an observation via external API."""

    # Hospital context
    hospital = serializers.CharField(max_length=200, required=True)

    # Classification
    category = serializers.UUIDField(required=False, allow_null=True, default=None)

    # Content
    title = serializers.CharField(max_length=300, required=False, allow_blank=True, default="")
    description = serializers.CharField(required=True)
    severity = serializers.ChoiceField(
        choices=[("low", "Low"), ("medium", "Medium"), ("high", "High"), ("critical", "Critical")],
        required=False,
        default="medium",
    )

    # Location and timing
    location_text = serializers.CharField(max_length=500, required=False, allow_blank=True, default="")
    incident_datetime = serializers.DateTimeField(required=False, allow_null=True, default=None)

    # Reporter info (all optional - anonymous supported)
    contact_name = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    contact_phone = serializers.CharField(max_length=20, required=False, allow_blank=True, default="")
    contact_email = serializers.EmailField(required=False, allow_blank=True, default="")
    reporter_staff_id = serializers.CharField(max_length=50, required=False, allow_blank=True, default="")

    # Patient info
    patient_file_number = serializers.CharField(max_length=100, required=False, allow_blank=True, default="")

    def validate_hospital(self, value):
        from apps.organizations.models import Hospital
        try:
            return Hospital.objects.get(name__iexact=value.strip())
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")

    def validate_category(self, value):
        if value is None:
            return None
        from apps.observations.models import ObservationCategory
        try:
            return ObservationCategory.objects.get(id=value)
        except ObservationCategory.DoesNotExist:
            raise serializers.ValidationError("Observation category not found.")


class ExternalObservationRetrieveSerializer(serializers.ModelSerializer):
    """Read-only serializer for retrieving an observation."""

    reference_number = serializers.CharField(source="tracking_code", read_only=True)
    hospital_name = serializers.CharField(source="hospital.name", read_only=True, default=None)
    category_name = serializers.CharField(source="category.name", read_only=True, default=None)
    contact_name = serializers.CharField(source="reporter_name", read_only=True)
    contact_phone = serializers.CharField(source="reporter_phone", read_only=True)
    contact_email = serializers.CharField(source="reporter_email", read_only=True)

    class Meta:
        model = Observation
        fields = [
            "id",
            "reference_number",
            "title",
            "description",
            "severity",
            "status",
            "location_text",
            "incident_datetime",
            "contact_name",
            "contact_phone",
            "contact_email",
            "reporter_staff_id",
            "patient_file_number",
            "hospital_name",
            "category_name",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields


# ---------------------------------------------------------------------------
# Appreciation
# ---------------------------------------------------------------------------

class ExternalAppreciationCreateSerializer(serializers.Serializer):
    """Public-facing fields for creating an appreciation via external API."""

    # Contact
    contact_name = serializers.CharField(max_length=200, required=True)
    contact_phone = serializers.CharField(max_length=20, required=True)

    # Content
    message = serializers.CharField(required=True)

    # Hospital context
    hospital = serializers.CharField(max_length=200, required=True)

    def validate_hospital(self, value):
        from apps.organizations.models import Hospital
        try:
            return Hospital.objects.get(name__iexact=value.strip())
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")


class ExternalAppreciationRetrieveSerializer(serializers.ModelSerializer):
    """Read-only serializer for retrieving an appreciation."""

    hospital_name = serializers.CharField(source="hospital.name", read_only=True)
    reference_number = serializers.SerializerMethodField()

    class Meta:
        model = Appreciation
        fields = [
            "id",
            "reference_number",
            "message_en",
            "status",
            "hospital_name",
            "is_anonymous",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields

    def get_reference_number(self, obj):
        if obj.metadata and "reference_number" in obj.metadata:
            return obj.metadata["reference_number"]
        return None


# ---------------------------------------------------------------------------
# Suggestion (Feedback)
# ---------------------------------------------------------------------------

class ExternalSuggestionCreateSerializer(serializers.Serializer):
    """Public-facing fields for creating a suggestion via external API."""

    # Contact
    contact_name = serializers.CharField(max_length=200, required=True)
    contact_phone = serializers.CharField(max_length=20, required=True)

    # Content
    title = serializers.CharField(max_length=500, required=False, allow_blank=True, default="")
    message = serializers.CharField(required=True)
    category = serializers.ChoiceField(
        choices=[
            ("clinical_care", "Clinical Care"),
            ("staff_service", "Staff Service"),
            ("facility", "Facility"),
            ("communication", "Communication"),
            ("appointment", "Appointment"),
            ("billing", "Billing"),
            ("food_service", "Food Service"),
            ("cleanliness", "Cleanliness"),
            ("technology", "Technology"),
            ("general", "General"),
            ("other", "Other"),
        ],
        required=False,
        default="general",
    )
    rating = serializers.IntegerField(min_value=1, max_value=5, required=False, allow_null=True, default=None)

    # Hospital context
    hospital = serializers.CharField(max_length=200, required=True)

    def validate_hospital(self, value):
        from apps.organizations.models import Hospital
        try:
            return Hospital.objects.get(name__iexact=value.strip())
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")


class ExternalSuggestionRetrieveSerializer(serializers.ModelSerializer):
    """Read-only serializer for retrieving a suggestion."""

    hospital_name = serializers.CharField(source="hospital.name", read_only=True)
    reference_number = serializers.SerializerMethodField()

    class Meta:
        model = Feedback
        fields = [
            "id",
            "reference_number",
            "title",
            "message",
            "category",
            "rating",
            "status",
            "feedback_type",
            "sentiment",
            "contact_name",
            "contact_phone",
            "hospital_name",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields

    def get_reference_number(self, obj):
        if obj.metadata and "reference_number" in obj.metadata:
            return obj.metadata["reference_number"]
        return None


class ExternalComplaintSatisfactionSerializer(serializers.Serializer):
    satisfaction = serializers.ChoiceField(
        choices=[
            ("satisfied", "Satisfied"),
            ("neutral", "Neutral"),
            ("dissatisfied", "Dissatisfied"),
            ("no_response", "No Response"),
        ],
        required=True,
    )


# ---------------------------------------------------------------------------
# Doctor Rating
# ---------------------------------------------------------------------------

class ExternalDoctorRatingCreateSerializer(serializers.Serializer):

    hospital_id = serializers.IntegerField(required=True)
    doctor_id = serializers.CharField(max_length=50, required=True)
    doctor_name = serializers.CharField(max_length=300, required=False, allow_blank=True, default="")
    rating = serializers.IntegerField(min_value=1, max_value=5, required=True)
    feedback = serializers.CharField(required=False, allow_blank=True, default="")
    rating_date = serializers.DateField(required=False, allow_null=True, default=None)
    patient_uhid = serializers.CharField(max_length=100, required=False, allow_blank=True, default="")
    patient_name = serializers.CharField(max_length=300, required=False, allow_blank=True, default="")
    patient_type = serializers.ChoiceField(
        choices=["IP", "OP", "ER", "DC"],
        required=False,
        allow_blank=True,
        default="",
    )
    department_name = serializers.CharField(max_length=200, required=False, allow_blank=True, default="")
    admit_date = serializers.DateField(required=False, allow_null=True, default=None)
    discharge_date = serializers.DateField(required=False, allow_null=True, default=None)

    def validate_hospital_id(self, value):
        from apps.organizations.models import Hospital

        try:
            return Hospital.objects.get(id=value)
        except Hospital.DoesNotExist:
            raise serializers.ValidationError("Hospital not found.")

    def validate_doctor_id(self, value):
        return value.strip()

    def validate(self, data):
        from apps.organizations.models import Staff

        hospital = data.get("hospital_id")
        doctor_id = data.get("doctor_id", "").strip()

        if hospital and doctor_id:
            staff = Staff.objects.filter(
                hospital=hospital, employee_id=doctor_id
            ).first()
            if not staff:
                raise serializers.ValidationError(
                    {
                        "doctor_id": f"Doctor with employee ID '{doctor_id}' not found at this hospital."
                    }
                )
            data["_staff"] = staff

        return data
