from rest_framework import serializers
from django.contrib.auth.password_validation import validate_password
from .models import *
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import Group, Permission
from django.db.models import Q
from django.conf import settings

class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = ['id', 'name']

class GroupUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomUser
        fields = ['id', 'first_name', 'last_name', 'email']

class CustomUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
    groups = serializers.SerializerMethodField()
    profile_image = serializers.SerializerMethodField()
    # email = serializers.EmailField(required=True, validators=[EmailValidator(message="Invalid email address")])
    class Meta:
        model = CustomUser
        fields = '__all__'
    
    def get_groups(self, obj):
        return obj.groups.first().name if obj.groups.exists() else None
    
    def get_profile_image(self, obj):
        if obj.profile_image and hasattr(obj.profile_image, 'url'):
            # request = self.context.get('request')
            return settings.URL+obj.profile_image.url
        return None
    
    def create(self,validated_data):
        password = self.initial_data.get('password')
        group = self.initial_data.get('group')
        first_name = self.initial_data.get('first_name')
        last_name = self.initial_data.get('last_name')
        if not group:
            raise serializers.ValidationError({"group": "Group is required"})
        if not first_name:
            raise serializers.ValidationError({"first_name": "First Name is required"})
        if not last_name:
            raise serializers.ValidationError({"last_name": "Last Name is required"})
        
        user = CustomUser.objects.create(email = validated_data['email'],first_name=first_name,last_name=last_name)
        user.set_password(password)
        user.save()
        return user

class OrganizationSerializer(serializers.ModelSerializer):
    organization_user = serializers.SerializerMethodField()
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    class Meta:
        model = Organization
        fields = ['id','org_name','organization_user','org_address', 'org_city', 'org_state', 'org_country', 
                  'org_zipcode', 'org_phone', 'org_email', 'email_notification_is_enabled', 'created_at', 
                  'created_by','updated_by','updated_at']
    
    def get_organization_user(self, obj):
        org_users = obj.organization_user.all().exclude(is_superuser = True).exclude(groups__name = 'super_admin')
        return GroupUserSerializer(org_users, many=True).data
    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None
        
class LocationSerializer(serializers.ModelSerializer):
    location_user_details = serializers.SerializerMethodField()
    org_name = serializers.CharField(source='organization.org_name', read_only=True)
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    class Meta:
        model = Location
        fields = ['id', 'loc_name','organization_id','org_name', 'loc_address', 'longitude', 'latitude', 'created_by','created_at','updated_by','updated_at','location_user_details']
    
    def get_location_user_details(self, obj):
        loc_users = obj.location_user.all().exclude(is_superuser = True).exclude(groups__name = 'super_admin')
        return GroupUserSerializer(loc_users, many=True).data
    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None
class AreaSerializer(serializers.ModelSerializer):
    area_user_details = serializers.SerializerMethodField()
    loc_name = serializers.CharField(source='location.loc_name', read_only=True)
    organization_id = serializers.CharField(source='location.organization.id', read_only=True)
    org_name = serializers.CharField(source='location.organization.org_name', read_only=True)
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    class Meta:
        model = Area
        fields = ['id','area_name',"organization_id",'org_name','location_id','loc_name', 'area_address', 'created_by', 'created_at','updated_by','updated_at','area_user_details']

    def get_area_user_details(self, obj):
        area_users = obj.area_user.all().exclude(is_superuser = True).exclude(groups__name = 'super_admin')
        return GroupUserSerializer(area_users, many=True).data
    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None
class CameraSerializer(serializers.ModelSerializer):
    camera_user_details = serializers.SerializerMethodField()
    organization_id = serializers.CharField(source='organization.id', read_only=True)
    org_name = serializers.CharField(source='organization.org_name', read_only=True)
    location_id = serializers.CharField(source='location.id', read_only=True)
    loc_name = serializers.CharField(source='location.loc_name', read_only=True)
    area_id = serializers.CharField(source='area.id', read_only=True)
    area_name = serializers.CharField(source='area.area_name', read_only=True)
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    class Meta:
        model = Camera
        fields = ['id','camera_name','organization_id','org_name','location_id','loc_name','area_id','area_name','port','frame_numbers','created_by', 'created_at','updated_by','updated_at','fps','ip_address','rtsp_url','is_enabled','camera_user_details']

    def get_camera_user_details(self, obj):
        cam_users = obj.camera_user.all().exclude(is_superuser = True).exclude(groups__name = 'super_admin')
        return GroupUserSerializer(cam_users, many=True).data
    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None
    
class CameraListWithoutPaginationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Camera
        fields = ['id','camera_name']


class CameraEventSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source='organization.org_name', read_only=True)
    location_name = serializers.CharField(source='location.loc_name', read_only=True)
    area_name = serializers.CharField(source='area.area_name', read_only=True)
    camera_name = serializers.CharField(source='camera.camera_name', read_only=True)
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    # Custom method field to return a list of event names

    # def get_camera_event(self, obj):
    #     import ipdb;ipdb.set_trace()
    #     # Assuming obj.camera_event is a list of event names
    #     return obj.camera_event
    class Meta:
        model = CameraEvent
        fields = ['id','camera_event','organization','organization_name','location','location_name','area','area_name','camera','camera_name','is_enabled','created_by', 'created_at','updated_by','updated_at']

    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None
    # def create(self, validated_data):
    #     camera_event = CameraEvent.objects.create(**validated_data)
    #     return camera_event
    
    # def get_frame(self, obj):
    #     if obj.frame and hasattr(obj.frame, 'url'):
    #         request = self.context.get('request')
    #         return request.build_absolute_uri(obj.frame.url)
    #     return None
    
class RoiSerializer(serializers.ModelSerializer):
    camera_name = serializers.CharField(source='camera.camera_name', read_only=True)
    camera_events_data = CameraEventSerializer(many=True, read_only=True, source = 'camera_events')
    created_by = serializers.SerializerMethodField()
    updated_by = serializers.SerializerMethodField()
    class Meta:
        model = Roi
        fields = ['id','roi_name','camera_events_data','camera','camera_name','frame_number','coordinates', 'start_time', 'end_time','color', 'created_by', 'created_at','updated_by','updated_at']

    def get_created_by(self, obj):
        if obj.created_by:
            created_by_user = CustomUserSerializer(obj.created_by).data
            if created_by_user['first_name'] and created_by_user['last_name']:
                return created_by_user['first_name'] + " " + created_by_user['last_name']
            elif created_by_user['first_name']:
                return created_by_user['first_name']
            elif created_by_user['last_name']:
                return created_by_user['last_name']
            else:
                return None
        return None
    def get_updated_by(self, obj):
        if obj.updated_by:
            updated_by_user = CustomUserSerializer(obj.updated_by).data
            if updated_by_user['first_name'] and updated_by_user['last_name']:
                return updated_by_user['first_name'] + " " + updated_by_user['last_name']
            elif updated_by_user['first_name']:
                return updated_by_user['first_name']
            elif updated_by_user['last_name']:
                return updated_by_user['last_name']
            else:
                return None
        return None

class StatusResponseSerializer(serializers.Serializer):
    status = serializers.CharField(default='success')
    message = serializers.CharField()

    def create(self, validated_data):
        return StatusResponse(**validated_data)

    def update(self, instance, validated_data):
        instance.status = validated_data.get('status', instance.status)
        instance.message = validated_data.get('message', instance.message)
        return instance

class StatusResponse:
    def __init__(self, status='success', message='Operation successful'):
        self.status = status
        self.message = message


class AlertSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source='organization.org_name', read_only=True)
    camera_name = serializers.CharField(source='camera.camera_name', read_only=True)
    camera_events_name = serializers.CharField(source='camera_events.camera_event', read_only=True)
    location_name = serializers.CharField(source='location.loc_name', read_only=True)
    area_name = serializers.CharField(source='area.area_name', read_only=True)
    frame = serializers.SerializerMethodField()
    class Meta:
        model = Alert
        fields = ['id','camera','camera_name','detection_choice','camera_events','camera_events_name','frame','area_name','location_name','organization_name','alert_message','is_enabled','created_at']

    def get_frame(self, obj):
        if obj.frame and hasattr(obj.frame, 'url'):
            request = self.context.get('request')
            return request.build_absolute_uri(obj.frame.url)
        return None
    

class VideoUploadSerializer(serializers.ModelSerializer):
    camera_events_name = serializers.CharField(source='camera_events.camera_event', read_only=True)
    camera_name = serializers.CharField(source='camera.camera_name', read_only=True)
    frame = serializers.SerializerMethodField()
    class Meta:
        model = Alert
        fields = ['id','created_at','frame','camera','camera_name','camera_events_name','camera_events','alert_message']

    def get_frame(self, obj):
        if obj.frame and hasattr(obj.frame, 'url'):
            request = self.context.get('request')
            return request.build_absolute_uri(obj.frame.url)
        return None
    
class QueueManagementSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source = 'roi.camera.organization.org_name', read_only = True)
    area_name = serializers.CharField(source = 'roi.camera.area.area_name', read_only = True)
    location_name = serializers.CharField(source = 'roi.camera.location.loc_name', read_only = True)
    # camera_events = CameraEventSerializer(many = True, read_only = True, source = 'roi.camera_events')
    camera_name = serializers.CharField(source = 'roi.camera.camera_name', read_only = True)
    class Meta:
        model = QueueManagement
        fields = ['id', 'organization_name', 'area_name', 'location_name', 'camera_name', 'currunt_queue_count', 'average_waiting_time', 'recomanded_staff_adjustment', 'action', 'created_at']

class HeatMappingSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source = 'roi.camera.organization.org_name', read_only = True)
    area_name = serializers.CharField(source = 'roi.camera.area.area_name', read_only = True)
    location_name = serializers.CharField(source = 'roi.camera.location.loc_name', read_only = True)
    # camera_events = CameraEventSerializer(many = True, read_only = True, source = 'roi.camera_events')
    camera_name = serializers.CharField(source = 'roi.camera.camera_name', read_only = True)
    roi_name = serializers.CharField(source='roi.roi_name', read_only=True)
    class Meta:
        model = HeatMapping
        fields = ['id','organization_name', 'area_name', 'location_name', 'camera_name','roi','roi_name','dwel_time']

class DemographicDetailsSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source = 'roi.camera.organization.org_name', read_only = True)
    area_name = serializers.CharField(source = 'roi.camera.area.area_name', read_only = True)
    location_name = serializers.CharField(source = 'roi.camera.location.loc_name', read_only = True)
    # camera_events = CameraEventSerializer(many = True, read_only = True, source = 'roi.camera_events')
    camera_name = serializers.CharField(source = 'roi.camera.camera_name', read_only = True)
    roi_name = serializers.CharField(source='roi.roi_name', read_only=True)
    
    class Meta:
        model = DemographicDetails
        fields = ['id', 'organization_name', 'area_name', 'location_name', 'camera_name','roi_name','age_range', 'unique_user', 'total_Events', 'average_age', 'median_age', 'mode_age']
        
class ParkingSerializer(serializers.ModelSerializer):
    organization_name = serializers.CharField(source = 'roi.camera.organization.org_name', read_only = True)
    area_name = serializers.CharField(source = 'roi.camera.area.area_name', read_only = True)
    location_name = serializers.CharField(source = 'roi.camera.location.loc_name', read_only = True)
    # camera_events = CameraEventSerializer(many = True, read_only = True, source = 'roi.camera_events')
    camera_name = serializers.CharField(source = 'roi.camera.camera_name', read_only = True)
    available_parking = serializers.SerializerMethodField()

    class Meta:
        model = Parking
        fields = ['id', 'organization_name', 'area_name', 'location_name', 'camera_name','total_count','occupied_parking' ,'available_parking']
    
    def get_available_parking(self, obj):
        if obj.total_count is not None and obj.occupied_parking is not None and obj.total_count > obj.occupied_parking:
            return obj.total_count - obj.occupied_parking
        return None
    
class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        model = Person
        fields = '__all__'

class ImageUploadSerializer(serializers.Serializer):
    image = serializers.ImageField()

class AlertPersonTrackingSerializer(serializers.ModelSerializer):
    alerts = serializers.SerializerMethodField()

    class Meta:
        model = AlertPersonTracking
        fields = ['id', 'tracking_id', 'alerts']

    def get_alerts(self, obj):
        request = self.context.get('request')
        return AlertSerializer(obj.alerts.all(), many=True, context={'request': request}).data
    