from rest_framework import serializers
from .models import Complaint, ComplaintCategory, ComplaintStatusHistory
from fuzzywuzzy import process
from tenants.models import Tenants
import hashlib
import uuid
from users.models import User_Roles

# A dictionary to simulate keyword-to-tenant routing
KEYWORD_TO_TENANT_MAPPING = {
    "transportation": "Ministry of Transport",
    "road": "Ministry of Transport",
    "traffic": "Ministry of Transport",
    "hospital": "Ministry of Health",
    "clinic": "Ministry of Health",
    "medical": "Ministry of Health",
    "school": "Ministry of Education and sports",
    "teacher": "Ministry of Education and sports",
    "water": "Ministry of Water and Environment",
    "environment": "Ministry of Water and Environment",
    "teachers": "Ministry of Education and sports",
}


class ComplaintCategorySerializer(serializers.ModelSerializer):
    """
    Serializes the ComplaintCategory model for read-only access.
    """

    class Meta:
        model = ComplaintCategory
        fields = ["category_id", "tenant", "name", "description"]
        read_only_fields = ["tenant", "name", "description"]



class ComplaintSerializer(serializers.ModelSerializer):
    """
    Serializer for the Complaint model. Handles both citizen submission and
    ministry officer updates.
    """

    # A read-only field to show the category name instead of the UUID
    category_name = serializers.ReadOnlyField(source="category.name")
    resolution_message = serializers.SerializerMethodField()

    class Meta:
        model = Complaint
        fields = [
            "complaint_id",
            "user",
            "tenant",
            "category",
            "short_description",
            "status",
            "complaint_text",
            "complaint_audio",
            "complaint_video",
            "timestamp",
            "category_name",
            "resolution_message",
        ]
        # CRITICAL FIX: Add 'tenant' to read_only_fields. This prevents validation from failing
        # because the field is missing from the request data. The 'create' method will
        # still be able to set it programmatically.
        read_only_fields = [
            "complaint_id",
            "status",
            "timestamp",
            "category_name",
            "tenant",
            "user"
            
        ]

    def get_resolution_message(self, obj):
     if obj.status == 'closed':
        last_closed = obj.status_history.filter(status='closed').order_by('-changed_at').first()
        if last_closed:
            return last_closed.resolution_message
     return None    

    def create(self, validated_data):
        """
        Custom create method to handle citizen-submitted complaints.
        Generates a user_hash or reuses an existing one.
        """

        # Step 2: Implement fuzzy keyword matching for routing
        short_description = validated_data.get("short_description", "").lower()

        best_match_tenant_name = None
        if short_description:
            best_match = process.extractOne(
                short_description, KEYWORD_TO_TENANT_MAPPING.keys(), score_cutoff=70
            )
            if best_match:
                keyword = best_match[0]
                best_match_tenant_name = KEYWORD_TO_TENANT_MAPPING[keyword]

        # Step 3: Assign the tenant based on the routing logic
        if best_match_tenant_name:
            try:
                tenant_instance = Tenants.objects.get(name=best_match_tenant_name)
                validated_data["tenant"] = tenant_instance
            except Tenants.DoesNotExist:
                default_tenant, _ = Tenants.objects.get_or_create(name="Default Tenant")
                validated_data["tenant"] = default_tenant
        else:
            default_tenant, _ = Tenants.objects.get_or_create(name="Default Tenant")
            validated_data["tenant"] = default_tenant

        # Step 4: Create the Complaint instance
        complaint = super().create(validated_data)

        # Step 5: Automatically create a status history record
        ComplaintStatusHistory.objects.create(
            complaint=complaint,
            status="received",
            changed_by=(
                self.context.get("request").user
                if self.context.get("request")
                and self.context.get("request").user.is_authenticated
                else None
            ),
        )
        return complaint
    


# Add 'resolution_message' to the ComplaintStatusHistorySerializer
class ComplaintStatusHistorySerializer(serializers.ModelSerializer):
    """
    Serializes the ComplaintStatusHistory model for logging status changes.
    """
    changed_by_username = serializers.ReadOnlyField(source="changed_by.username")

    class Meta:
        model = ComplaintStatusHistory
        fields = ["id", "complaint", "status", "changed_at", "changed_by_username", "resolution_message"]
        read_only_fields = ["id", "complaint", "status", "changed_at"]


# Create a new serializer for the ministry officer's PATCH request.
# Place this new serializer right after ComplaintSerializer.
class MinistryComplaintUpdateSerializer(serializers.ModelSerializer):
    """
    A custom serializer for ministry officers to update a complaint.
    Only allows 'status' and 'resolution_message' fields.
    """
    resolution_message = serializers.CharField(
        required=False, allow_blank=True
    )
    
    class Meta:
        model = Complaint
        fields = ["status", "resolution_message"]

    def validate(self, data):
        new_status = data.get("status")
        resolution_message = data.get("resolution_message")

        # Check if the new status is 'closed' and if a resolution message is provided
        if new_status == 'closed' and not resolution_message:
            raise serializers.ValidationError(
                {"resolution_message": "A resolution message is required when closing a complaint."}
            )
        
        return data    


class CitizenComplaintReadSerializer(serializers.ModelSerializer):
    """
    Serializer for reading citizen complaints, returning full URLs for media files.
    """

    category = ComplaintCategorySerializer(read_only=True)
    complaint_audio = serializers.SerializerMethodField()
    complaint_video = serializers.SerializerMethodField()
    user_hash = serializers.SerializerMethodField()
    resolution_message = serializers.SerializerMethodField()

    class Meta:
        model = Complaint
        fields = [
            "complaint_id",
            "user_hash",
            "category",
            "short_description",
            "status",
            "complaint_text",
            "timestamp",
            "complaint_audio",
            "complaint_video",
            "resolution_message",
        ]

    def get_user_hash(self, obj):
        # Hash the user's email securely using SHA256
        if obj.user and obj.user.email:
            return hashlib.sha256(obj.user.email.encode("utf-8")).hexdigest()
        return None

    def get_complaint_audio(self, obj):
        # Return the full URL if the file exists, otherwise None
        if obj.complaint_audio:
            request = self.context.get("request")
            audio_url = request.build_absolute_uri(obj.complaint_audio.url)
            print(f"Generated Audio URL: {audio_url}")  # Add this for debugging
            return audio_url
        return None

    def get_complaint_video(self, obj):
        # Return the full URL if the file exists, otherwise None
        if obj.complaint_video:
            request = self.context.get("request")
            video_url = request.build_absolute_uri(obj.complaint_video.url)
            print(f"Generated Video URL: {video_url}")  # Add this for debugging
            return video_url
        return None
    
    def get_resolution_message(self, obj):
      if obj.status == 'closed':
          last_closed = obj.status_history.filter(status='closed').order_by('-changed_at').first()
          if last_closed:
            return last_closed.resolution_message
      return None
    

class ComplaintStatisticsSerializer(serializers.Serializer):
    """
    Serializer for the complaint statistics data structure.
    It's not tied to a model, but defines the expected JSON output format.
    """
    total_complaints = serializers.IntegerField(
        help_text="The total number of complaints submitted by the user."
    )
    received_complaints = serializers.IntegerField(
        help_text="The number of complaints with 'received' status."
    )
    pending_complaints = serializers.IntegerField(
        help_text="The number of complaints with 'pending' status."
    )
    closed_complaints = serializers.IntegerField(
        help_text="The number of complaints with 'closed' status (Resolved)."
    )    
    


