"""
Serializers for Business APIs
"""

from datetime import timedelta
from django.utils import timezone
from rest_framework import serializers
from .models import (
    Category, SubCategory, Business, BusinessImage, BusinessVideo,
    Service, ServiceImage, Employee, PastExperience, PastExperienceImage,
    Review, ReviewImage, ChatRoom, ChatMessage, Notification, BusinessHours,
    Feedback, BusinessBranch, Post, Offer, LeadEvent, ContactRequest,
    NewsletterSubscriber, Report, Request, RequestResponse, Campaign,
    Plan, Subscription, Payment, AuditLog, PlatformSettings
)
from authentication.serializers import UserSerializer


class SubCategorySerializer(serializers.ModelSerializer):
    """Serializer for SubCategory model"""
    category_name = serializers.CharField(source='category.name', read_only=True)
    business_count = serializers.SerializerMethodField()

    class Meta:
        model = SubCategory
        fields = ['id', 'category', 'category_name', 'name', 'slug', 'description', 'icon', 'is_active', 'business_count', 'created_at']
        read_only_fields = ['id', 'slug', 'category_name', 'business_count', 'created_at']

    def get_business_count(self, obj):
        """Return the count of active businesses in this sub-category"""
        return obj.businesses.filter(is_active=True).count()


class CategorySerializer(serializers.ModelSerializer):
    """Serializer for Category model with sub-categories"""
    sub_categories = SubCategorySerializer(many=True, read_only=True)
    business_count = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ['id', 'name', 'slug', 'description', 'icon', 'is_active', 'sub_categories', 'business_count', 'created_at']
        read_only_fields = ['id', 'slug', 'business_count', 'created_at']

    def get_business_count(self, obj):
        """Return the count of active businesses directly in this category"""
        return obj.businesses.filter(is_active=True).count()


class BusinessHoursSerializer(serializers.ModelSerializer):
    """Serializer for Business Operating Hours"""
    day_name = serializers.CharField(source='get_day_of_week_display', read_only=True)

    class Meta:
        model = BusinessHours
        fields = ['id', 'day_of_week', 'day_name', 'opening_time', 'closing_time', 'is_closed', 'is_24_hours']
        read_only_fields = ['id', 'day_name']


class BusinessImageSerializer(serializers.ModelSerializer):
    """Serializer for Business Images"""

    class Meta:
        model = BusinessImage
        fields = ['id', 'image', 'caption', 'is_main', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class BusinessVideoSerializer(serializers.ModelSerializer):
    """Serializer for Business Videos"""

    class Meta:
        model = BusinessVideo
        fields = ['id', 'video', 'video_url', 'thumbnail', 'title', 'description', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class ServiceImageSerializer(serializers.ModelSerializer):
    """Serializer for Listing gallery images"""

    class Meta:
        model = ServiceImage
        fields = ['id', 'image', 'caption', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class ServiceSerializer(serializers.ModelSerializer):
    """Serializer for Services / Listings"""
    images = ServiceImageSerializer(many=True, read_only=True)
    category_name = serializers.CharField(source='category.name', read_only=True, allow_null=True)

    class Meta:
        model = Service
        fields = [
            'id', 'service_id', 'slug', 'sku', 'name', 'description', 'image', 'images',
            'category', 'category_name', 'price', 'discount_price', 'price_type',
            'availability', 'cta_type', 'purchase_url', 'booking_url',
            'is_active', 'created_at',
        ]
        read_only_fields = ['id', 'service_id', 'slug', 'images', 'category_name', 'created_at']


class ListingDetailSerializer(serializers.ModelSerializer):
    """
    Serializer for a single listing (product/service) with its business
    context nested — used by the public /product/:slug page, which has no
    business context of its own in the URL.
    """
    images = ServiceImageSerializer(many=True, read_only=True)
    category_name = serializers.CharField(source='category.name', read_only=True, allow_null=True)
    business = serializers.SerializerMethodField()

    class Meta:
        model = Service
        fields = [
            'id', 'service_id', 'slug', 'sku', 'name', 'description', 'image', 'images',
            'category', 'category_name', 'price', 'discount_price', 'price_type',
            'availability', 'cta_type', 'purchase_url', 'booking_url',
            'is_active', 'created_at', 'business',
        ]

    def get_business(self, obj):
        return BusinessListSerializer(obj.business, context=self.context).data


class OfferListSerializer(serializers.ModelSerializer):
    """
    Serializer for the public Offers page. Offers have no image of their
    own — fall back to the linked listing's image, then the business's.
    """
    business_title = serializers.CharField(source='business.title', read_only=True)
    business_slug = serializers.CharField(source='business.slug', read_only=True)
    category = serializers.SerializerMethodField()
    image = serializers.SerializerMethodField()
    listing_slug = serializers.CharField(source='listing.slug', read_only=True, allow_null=True)

    class Meta:
        model = Offer
        fields = [
            'id', 'title', 'terms', 'original_price', 'offer_price',
            'start_at', 'end_at', 'business_title', 'business_slug',
            'listing_slug', 'category', 'image', 'is_featured', 'created_at',
        ]

    def get_category(self, obj):
        categories = obj.business.get_categories()
        return categories[0].name if categories else 'Business'

    def get_image(self, obj):
        request = self.context.get('request')
        if obj.image:
            return request.build_absolute_uri(obj.image.url) if request else obj.image.url
        if obj.listing and obj.listing.image:
            return request.build_absolute_uri(obj.listing.image.url) if request else obj.listing.image.url
        main_image = obj.business.images.filter(is_main=True).first()
        if main_image:
            return request.build_absolute_uri(main_image.image.url) if request else main_image.image.url
        first_image = obj.business.images.first()
        if first_image:
            return request.build_absolute_uri(first_image.image.url) if request else first_image.image.url
        return None


class EmployeeSerializer(serializers.ModelSerializer):
    """Serializer for Employees"""

    class Meta:
        model = Employee
        fields = ['id', 'employee_id', 'name', 'designation', 'image', 'bio', 'phone_number', 'email', 'is_active', 'joined_date']
        read_only_fields = ['id', 'employee_id']


class PastExperienceImageSerializer(serializers.ModelSerializer):
    """Serializer for Past Experience Images"""

    class Meta:
        model = PastExperienceImage
        fields = ['id', 'image', 'caption', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class PastExperienceSerializer(serializers.ModelSerializer):
    """Serializer for Past Experience"""
    images = PastExperienceImageSerializer(many=True, read_only=True)

    class Meta:
        model = PastExperience
        fields = ['id', 'title', 'description', 'client_name', 'completion_date', 'project_value', 'images', 'created_at']
        read_only_fields = ['id', 'created_at']


class ReviewImageSerializer(serializers.ModelSerializer):
    """Serializer for Review Images"""

    class Meta:
        model = ReviewImage
        fields = ['id', 'image', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class ReviewSerializer(serializers.ModelSerializer):
    """Serializer for Reviews"""
    user = UserSerializer(read_only=True)
    images = ReviewImageSerializer(many=True, read_only=True)
    user_name = serializers.SerializerMethodField()
    user_image = serializers.SerializerMethodField()

    class Meta:
        model = Review
        fields = [
            'id', 'business', 'user', 'user_name', 'user_image',
            'rating', 'message', 'response', 'response_date',
            'is_approved', 'is_featured', 'images',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'user', 'response', 'response_date', 'is_approved', 'created_at', 'updated_at']

    def get_user_name(self, obj):
        """Get reviewer's full name"""
        return obj.user.get_full_name()

    def get_user_image(self, obj):
        """Get reviewer's profile picture"""
        if obj.user.profile_picture:
            return obj.user.profile_picture.url
        return None


class ReviewCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating reviews"""

    class Meta:
        model = Review
        fields = ['business', 'rating', 'message']

    def validate_rating(self, value):
        """Validate rating is between 1 and 5"""
        if value < 1 or value > 5:
            raise serializers.ValidationError("Rating must be between 1 and 5")
        return value

    def validate(self, attrs):
        """Anti-abuse rules: one review per user per business, and a business
        cannot review itself — protects the average_rating a business
        actually earns."""
        user = self.context['request'].user
        business = attrs['business']

        if business.owner_id == user.id:
            raise serializers.ValidationError("You can't review your own business.")

        if business.memberships.filter(user=user, status='active').exists():
            raise serializers.ValidationError("You can't review a business you're a team member of.")

        if Review.objects.filter(user=user, business=business).exists():
            raise serializers.ValidationError("You have already reviewed this business")

        return attrs


class BusinessListSerializer(serializers.ModelSerializer):
    """
    Lightweight serializer for business list views (dashboard, sections)
    """
    sub_categories = SubCategorySerializer(many=True, read_only=True)
    categories = serializers.SerializerMethodField()  # Main categories (now directly linked)
    main_image = serializers.SerializerMethodField()
    owner_name = serializers.SerializerMethodField()
    distance = serializers.SerializerMethodField()  # Will be calculated based on user location
    share_url = serializers.SerializerMethodField()  # Shareable link
    is_open = serializers.SerializerMethodField()  # Current open status
    today_hours = serializers.SerializerMethodField()  # Today's operating hours
    is_sponsored = serializers.SerializerMethodField()  # Set by search_businesses for an active-campaign match; not a DB column

    class Meta:
        model = Business
        fields = [
            'id', 'title', 'slug', 'description', 'logo', 'profile_image', 'main_image',
            'categories', 'sub_categories', 'owner_name',
            'latitude', 'longitude', 'address', 'city',
            'phone_number', 'whatsapp_number', 'website_link',
            'is_verified', 'is_active', 'is_featured', 'provides_home_service',
            'average_rating', 'total_reviews', 'view_count',
            'distance', 'share_url', 'is_open', 'today_hours', 'created_at', 'is_sponsored'
        ]

    def get_is_sponsored(self, obj):
        return getattr(obj, 'is_sponsored', False)

    def get_categories(self, obj):
        """Get unique main categories from sub-categories"""
        categories = obj.get_categories()
        return CategorySerializer(categories, many=True).data

    def get_main_image(self, obj):
        """Get the main showcase image"""
        main_image = obj.images.filter(is_main=True).first()
        if main_image:
            return main_image.image.url
        # If no main image, return first image
        first_image = obj.images.first()
        if first_image:
            return first_image.image.url
        return None

    def get_owner_name(self, obj):
        """Get business owner's name"""
        return obj.owner.get_full_name()

    def get_distance(self, obj):
        """
        Calculate distance from user's location
        This will be set in the view after calculation
        """
        return getattr(obj, 'distance', None)

    def get_share_url(self, obj):
        """Get shareable URL path for this business"""
        return obj.get_share_url()

    def get_is_open(self, obj):
        """Get current open/closed status"""
        return obj.is_open_now()

    def get_today_hours(self, obj):
        """Get today's operating hours"""
        today_hours = obj.get_today_hours()
        if today_hours:
            return BusinessHoursSerializer(today_hours).data
        return None


class BusinessDetailSerializer(serializers.ModelSerializer):
    """
    Detailed serializer for single business view
    Includes all related data
    """
    sub_categories = SubCategorySerializer(many=True, read_only=True)
    categories = serializers.SerializerMethodField()  # Main categories (now directly linked)
    images = BusinessImageSerializer(many=True, read_only=True)
    videos = BusinessVideoSerializer(many=True, read_only=True)
    services = ServiceSerializer(many=True, read_only=True)
    employees = EmployeeSerializer(many=True, read_only=True)
    past_experiences = PastExperienceSerializer(many=True, read_only=True)
    reviews = serializers.SerializerMethodField()
    owner = UserSerializer(read_only=True)
    share_url = serializers.SerializerMethodField()  # Shareable link
    operating_hours = BusinessHoursSerializer(many=True, read_only=True)  # All operating hours
    is_open = serializers.SerializerMethodField()  # Current open status
    today_hours = serializers.SerializerMethodField()  # Today's hours
    is_favorite = serializers.SerializerMethodField()  # User's favorite status
    is_following = serializers.SerializerMethodField()  # User's follow status
    posts = serializers.SerializerMethodField()  # Published posts — the public-facing side of the Posts content flywheel

    class Meta:
        model = Business
        fields = [
            'id', 'owner', 'title', 'slug', 'description', 'logo', 'profile_image',
            'categories', 'sub_categories', 'images', 'videos',
            'latitude', 'longitude', 'address', 'city', 'country',
            'phone_number', 'whatsapp_number', 'website_link', 'facebook_link', 'instagram_link', 'email',
            'is_verified', 'is_active', 'is_featured', 'provides_home_service',
            'total_reviews', 'average_rating', 'view_count',
            'services', 'employees', 'past_experiences', 'reviews', 'posts',
            'operating_hours', 'is_open', 'today_hours', 'is_favorite', 'is_following',
            'share_url', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'owner', 'slug', 'is_active', 'is_featured', 'total_reviews', 'average_rating', 'view_count', 'share_url', 'created_at', 'updated_at']

    def get_reviews(self, obj):
        approved = obj.reviews.filter(is_approved=True)
        return ReviewSerializer(approved, many=True, context=self.context).data

    def get_posts(self, obj):
        published = obj.posts.filter(status='published').order_by('-published_at')
        return PostSerializer(published, many=True, context=self.context).data

    def get_categories(self, obj):
        """Get unique main categories from sub-categories"""
        categories = obj.get_categories()
        return CategorySerializer(categories, many=True).data

    def get_share_url(self, obj):
        """Get shareable URL path for this business"""
        return obj.get_share_url()

    def get_is_open(self, obj):
        """Get current open/closed status"""
        return obj.is_open_now()

    def get_today_hours(self, obj):
        """Get today's operating hours"""
        today_hours = obj.get_today_hours()
        if today_hours:
            return BusinessHoursSerializer(today_hours).data
        return None

    def get_is_favorite(self, obj):
        """Check if current user has favorited this business"""
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            return request.user.favorite_businesses.filter(id=obj.id).exists()
        return False

    def get_is_following(self, obj):
        """Check if current user follows this business"""
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            return request.user.following_businesses.filter(id=obj.id).exists()
        return False


class BusinessCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating/updating businesses"""
    categories = serializers.PrimaryKeyRelatedField(
        queryset=Category.objects.filter(is_active=True),
        many=True,
        required=False
    )

    class Meta:
        model = Business
        fields = [
            'title', 'description', 'logo', 'profile_image',
            'categories', 'sub_categories',
            'latitude', 'longitude', 'address', 'city', 'country',
            'phone_number', 'whatsapp_number', 'website_link', 'facebook_link', 'instagram_link', 'email',
            'provides_home_service'
        ]

    def validate(self, attrs):
        """Validate required fields"""
        if not attrs.get('title'):
            raise serializers.ValidationError({"title": "Title is required"})
        description = attrs.get('description', '')
        if not description:
            raise serializers.ValidationError({"description": "Description is required"})
        if len(description) > 1000:
            raise serializers.ValidationError(
                {"description": "Description cannot exceed 1000 characters."}
            )
        # Now allow either categories or sub_categories
        if not attrs.get('categories') and not attrs.get('sub_categories'):
            raise serializers.ValidationError({"categories": "At least one category is required"})
        return attrs


class DashboardSectionSerializer(serializers.Serializer):
    """
    Serializer for dashboard sections
    """
    section_name = serializers.CharField()
    section_type = serializers.CharField()
    businesses = BusinessListSerializer(many=True)
    total_count = serializers.IntegerField()


# ==================== Review Serializers ====================

class ReviewImageSerializer(serializers.ModelSerializer):
    """Serializer for review images"""

    class Meta:
        model = ReviewImage
        fields = ['id', 'image', 'uploaded_at']
        read_only_fields = ['id', 'uploaded_at']


class ReviewListSerializer(serializers.ModelSerializer):
    """Serializer for listing reviews"""
    user_name = serializers.CharField(source='user.get_full_name', read_only=True)
    user_image = serializers.ImageField(source='user.profile_picture', read_only=True)
    images = ReviewImageSerializer(many=True, read_only=True)

    class Meta:
        model = Review
        fields = [
            'id', 'user', 'user_name', 'user_image',
            'rating', 'message', 'images',
            'response', 'response_date',
            'is_approved', 'is_featured', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'user', 'user_name', 'user_image', 'created_at', 'updated_at']


class MyReviewSerializer(serializers.ModelSerializer):
    """Serializer for user's own reviews with business info"""
    images = ReviewImageSerializer(many=True, read_only=True)
    business_id = serializers.IntegerField(source='business.id', read_only=True)
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_image = serializers.SerializerMethodField()
    business_slug = serializers.CharField(source='business.slug', read_only=True)

    class Meta:
        model = Review
        fields = [
            'id', 'business_id', 'business_name', 'business_image', 'business_slug',
            'rating', 'message', 'images',
            'response', 'response_date',
            'is_featured', 'is_approved', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']

    def get_business_image(self, obj):
        """Get the main image of the business (check images first, then logo)"""
        # First try to get main image from business images
        main_image = obj.business.images.filter(is_main=True).first()
        if main_image:
            return main_image.image.url
        # Then try first image
        first_image = obj.business.images.first()
        if first_image:
            return first_image.image.url
        # Finally fallback to logo
        if obj.business.logo:
            return obj.business.logo.url
        return None


# ==================== Chat Serializers ====================

class ChatMessageSerializer(serializers.ModelSerializer):
    """Serializer for chat messages"""
    sender_name = serializers.SerializerMethodField()

    class Meta:
        model = ChatMessage
        fields = [
            'id', 'sender_type', 'sender_name', 'message', 'image',
            'is_read', 'read_at', 'created_at'
        ]
        read_only_fields = ['id', 'sender_name', 'is_read', 'read_at', 'created_at']

    def get_sender_name(self, obj):
        if obj.sender_type == 'user' and obj.sender_user:
            return obj.sender_user.get_full_name()
        elif obj.sender_type == 'business':
            return obj.room.business.title
        return 'Unknown'


class ChatRoomListSerializer(serializers.ModelSerializer):
    """Serializer for listing chat rooms"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_logo = serializers.ImageField(source='business.logo', read_only=True)
    user_name = serializers.CharField(source='user.get_full_name', read_only=True)
    user_image = serializers.ImageField(source='user.profile_picture', read_only=True)
    unread_count = serializers.SerializerMethodField()

    class Meta:
        model = ChatRoom
        fields = [
            'id', 'business', 'business_name', 'business_logo',
            'user', 'user_name', 'user_image',
            'last_message', 'last_message_time', 'last_message_by',
            'unread_count', 'updated_at'
        ]
        read_only_fields = ['id', 'business_name', 'business_logo', 'user_name', 'user_image', 'updated_at']

    def get_unread_count(self, obj):
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            # Check if user is the customer or business owner
            if obj.user == request.user:
                return obj.unread_count_user
            elif obj.business.owner == request.user:
                return obj.unread_count_business
        return 0


class ChatRoomDetailSerializer(serializers.ModelSerializer):
    """Serializer for chat room detail with messages"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_logo = serializers.ImageField(source='business.logo', read_only=True)
    user_name = serializers.CharField(source='user.get_full_name', read_only=True)
    user_image = serializers.ImageField(source='user.profile_picture', read_only=True)
    messages = ChatMessageSerializer(many=True, read_only=True)

    class Meta:
        model = ChatRoom
        fields = [
            'id', 'business', 'business_name', 'business_logo',
            'user', 'user_name', 'user_image',
            'messages', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'business_name', 'business_logo', 'user_name', 'user_image', 'created_at', 'updated_at']


class SendMessageSerializer(serializers.ModelSerializer):
    """Serializer for sending messages"""

    class Meta:
        model = ChatMessage
        fields = ['message', 'image']

    def validate(self, attrs):
        if not attrs.get('message') and not attrs.get('image'):
            raise serializers.ValidationError("Message or image is required")
        return attrs


# ==================== Notification Serializers ====================

class NotificationSerializer(serializers.ModelSerializer):
    """Serializer for notifications"""
    business_name = serializers.SerializerMethodField()
    business_logo = serializers.SerializerMethodField()

    class Meta:
        model = Notification
        fields = [
            'id', 'notification_type', 'title', 'message',
            'business', 'business_name', 'business_logo',
            'action_url', 'is_read', 'read_at', 'created_at'
        ]
        read_only_fields = ['id', 'business_name', 'business_logo', 'created_at']

    def get_business_name(self, obj):
        # business FK is nullable — guard against None to prevent AttributeError
        if obj.business_id and obj.business:
            return obj.business.title
        return None

    def get_business_logo(self, obj):
        if obj.business_id and obj.business and obj.business.logo:
            return obj.business.logo.url
        return None


# ==================== User Favorites Serializer ====================

class FavoriteBusinessSerializer(serializers.ModelSerializer):
    """Serializer for favorite businesses"""
    main_image = serializers.SerializerMethodField()
    sub_categories = SubCategorySerializer(many=True, read_only=True)
    categories = serializers.SerializerMethodField()
    distance = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True, required=False)
    is_open = serializers.SerializerMethodField()
    today_hours = serializers.SerializerMethodField()

    class Meta:
        model = Business
        fields = [
            'id', 'title', 'slug', 'description', 'logo', 'profile_image', 'main_image',
            'categories', 'sub_categories', 'latitude', 'longitude', 'address', 'city',
            'phone_number', 'whatsapp_number', 'website_link',
            'is_verified', 'provides_home_service',
            'average_rating', 'total_reviews', 'distance',
            'is_open', 'today_hours'
        ]

    def get_categories(self, obj):
        """Get unique main categories from sub-categories"""
        categories = obj.get_categories()
        return CategorySerializer(categories, many=True).data

    def get_main_image(self, obj):
        main_img = obj.images.filter(is_main=True).first()
        if main_img and main_img.image:
            return main_img.image.url
        return None

    def get_is_open(self, obj):
        """Get current open/closed status"""
        return obj.is_open_now()

    def get_today_hours(self, obj):
        """Get today's operating hours"""
        today_hours = obj.get_today_hours()
        if today_hours:
            return BusinessHoursSerializer(today_hours).data
        return None


# ==================== Feedback Serializers ====================

class FeedbackSerializer(serializers.ModelSerializer):
    """Serializer for feedback listing"""
    user_name = serializers.CharField(source='user.get_full_name', read_only=True, allow_null=True)
    user_email = serializers.EmailField(source='user.email', read_only=True, allow_null=True)

    class Meta:
        model = Feedback
        fields = [
            'id', 'user', 'user_name', 'user_email',
            'title', 'message', 'category', 'rating',
            'status', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'user', 'user_name', 'user_email', 'status', 'created_at', 'updated_at']


class FeedbackCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating feedback"""

    class Meta:
        model = Feedback
        fields = ['title', 'message', 'category', 'rating', 'device_info']

    def validate_title(self, value):
        """Validate title is not empty"""
        if not value or len(value.strip()) < 3:
            raise serializers.ValidationError("Title must be at least 3 characters")
        return value.strip()

    def validate_message(self, value):
        """Validate message is not too short"""
        if not value or len(value.strip()) < 10:
            raise serializers.ValidationError("Message must be at least 10 characters")
        return value.strip()

    def validate_category(self, value):
        """Validate category is valid"""
        valid_categories = ['general', 'bug_report', 'feature_request', 'improvement', 'other']
        if value not in valid_categories:
            raise serializers.ValidationError(f"Invalid category. Choose from: {', '.join(valid_categories)}")
        return value

    def validate_rating(self, value):
        """Validate rating is between 1 and 5"""
        if value is not None and (value < 1 or value > 5):
            raise serializers.ValidationError("Rating must be between 1 and 5")
        return value


# ==================== Branch Serializers ====================

class BusinessBranchSerializer(serializers.ModelSerializer):
    """Serializer for additional business locations"""

    class Meta:
        model = BusinessBranch
        fields = [
            'id', 'name', 'address', 'city', 'country', 'latitude', 'longitude',
            'phone_number', 'whatsapp_number', 'is_main', 'is_active', 'created_at',
        ]
        read_only_fields = ['id', 'created_at']


# ==================== Post Serializers ====================

class PostSerializer(serializers.ModelSerializer):
    """Serializer for reading posts"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    listing_name = serializers.CharField(source='listing.name', read_only=True, allow_null=True)
    listing_slug = serializers.CharField(source='listing.slug', read_only=True, allow_null=True)

    class Meta:
        model = Post
        fields = [
            'id', 'business', 'business_name', 'post_type', 'caption', 'image', 'video',
            'listing', 'listing_name', 'listing_slug', 'cta_type', 'status', 'scheduled_for',
            'published_at', 'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'business_name', 'listing_name', 'listing_slug', 'published_at', 'created_at', 'updated_at']


class PostCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating/editing a post"""

    class Meta:
        model = Post
        fields = ['post_type', 'caption', 'image', 'video', 'listing', 'cta_type', 'status', 'scheduled_for']

    def validate_caption(self, value):
        if not value or len(value.strip()) < 3:
            raise serializers.ValidationError("Caption must be at least 3 characters")
        return value.strip()


# ==================== Offer Serializers ====================

class OfferSerializer(serializers.ModelSerializer):
    """Serializer for reading/creating offers"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    is_live = serializers.SerializerMethodField()

    class Meta:
        model = Offer
        fields = [
            'id', 'business', 'business_name', 'listing', 'title', 'image', 'original_price',
            'offer_price', 'terms', 'start_at', 'end_at', 'is_active', 'is_featured', 'is_live', 'created_at',
        ]
        read_only_fields = ['id', 'business', 'business_name', 'is_featured', 'is_live', 'created_at']

    def get_is_live(self, obj):
        return obj.is_live()

    def validate(self, data):
        start_at = data.get('start_at', getattr(self.instance, 'start_at', None))
        end_at = data.get('end_at', getattr(self.instance, 'end_at', None))
        if start_at and end_at and end_at <= start_at:
            raise serializers.ValidationError("end_at must be after start_at")
        return data


# ==================== Lead Event Serializers ====================

class LeadEventCreateSerializer(serializers.ModelSerializer):
    """Serializer for recording a tracked customer-contact action (CTA click)"""

    class Meta:
        model = LeadEvent
        fields = ['event_type', 'source', 'listing', 'post', 'session_id']

    def validate_listing(self, value):
        if value is not None and value.business_id != self.context['business'].id:
            raise serializers.ValidationError("Listing does not belong to this business")
        return value

    def validate_post(self, value):
        if value is not None and value.business_id != self.context['business'].id:
            raise serializers.ValidationError("Post does not belong to this business")
        return value


class LeadEventListSerializer(serializers.ModelSerializer):
    """Serializer for a business owner's Leads page — who contacted them and how"""
    event_type_display = serializers.CharField(source='get_event_type_display', read_only=True)
    user_name = serializers.SerializerMethodField()
    user_email = serializers.EmailField(source='user.email', read_only=True, allow_null=True)
    listing_name = serializers.CharField(source='listing.name', read_only=True, allow_null=True)

    class Meta:
        model = LeadEvent
        fields = [
            'id', 'event_type', 'event_type_display', 'source',
            'user_name', 'user_email', 'listing_name', 'status', 'note', 'created_at',
        ]

    def get_user_name(self, obj):
        if obj.user:
            return obj.user.get_full_name() or obj.user.email
        return 'Anonymous visitor'


# ==================== Contact Request Serializers ====================

class ContactRequestCreateSerializer(serializers.ModelSerializer):
    """Serializer for public sales/support inquiries (pricing page, plan upgrade requests)"""

    class Meta:
        model = ContactRequest
        fields = ['full_name', 'email', 'phone_number', 'message', 'source', 'business']

    def validate_full_name(self, value):
        if not value or len(value.strip()) < 2:
            raise serializers.ValidationError("Please enter your full name.")
        return value.strip()

    def validate_message(self, value):
        if not value or len(value.strip()) < 5:
            raise serializers.ValidationError("Please add a short message so we know how to help.")
        return value.strip()


class ContactRequestListSerializer(serializers.ModelSerializer):
    """Read serializer for the admin Support console"""
    business_name = serializers.CharField(source='business.title', read_only=True, allow_null=True)
    source_display = serializers.CharField(source='get_source_display', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = ContactRequest
        fields = [
            'id', 'full_name', 'email', 'phone_number', 'message',
            'source', 'source_display', 'business', 'business_name',
            'status', 'status_display', 'created_at',
        ]


class AdminCategorySerializer(serializers.ModelSerializer):
    """Create/edit serializer for the admin Categories console"""

    class Meta:
        model = Category
        fields = ['id', 'name', 'slug', 'description', 'icon', 'is_active']
        read_only_fields = ['id', 'slug']


class AdminSubCategorySerializer(serializers.ModelSerializer):
    """Create/edit serializer for the admin Categories console"""

    class Meta:
        model = SubCategory
        fields = ['id', 'category', 'name', 'slug', 'description', 'icon', 'is_active']
        read_only_fields = ['id', 'slug']


class NewsletterSubscriberSerializer(serializers.ModelSerializer):
    """
    Serializer for the footer newsletter signup form. `email` is declared
    explicitly (rather than left to ModelSerializer's auto-generation) to
    skip the automatic UniqueValidator — re-subscribing an existing (active
    or previously-unsubscribed) address is a valid, expected request here,
    handled by the view's get_or_create/reactivate logic rather than
    rejected at the serializer.
    """
    email = serializers.EmailField()

    class Meta:
        model = NewsletterSubscriber
        fields = ['email']

    def validate_email(self, value):
        return value.strip().lower()


class ReportCreateSerializer(serializers.ModelSerializer):
    """Serializer for the "Report business" button on Business Profile"""

    class Meta:
        model = Report
        fields = ['reason', 'message']


class ReportListSerializer(serializers.ModelSerializer):
    """Read serializer for admin-app's Content Moderation console"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_slug = serializers.CharField(source='business.slug', read_only=True)
    reporter_email = serializers.EmailField(source='reporter.email', read_only=True)
    reason_display = serializers.CharField(source='get_reason_display', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Report
        fields = [
            'id', 'business', 'business_name', 'business_slug',
            'reporter_email', 'reason', 'reason_display', 'message',
            'status', 'status_display', 'created_at',
        ]


# ==================== Customer Requests ====================

class RequestResponseSerializer(serializers.ModelSerializer):
    """A business's reply to a Request — read by the requester on My Requests"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_slug = serializers.CharField(source='business.slug', read_only=True)
    business_logo = serializers.SerializerMethodField()

    class Meta:
        model = RequestResponse
        fields = ['id', 'business', 'business_name', 'business_slug', 'business_logo', 'message', 'created_at']

    def get_business_logo(self, obj):
        return obj.business.logo.url if obj.business.logo else None


class RequestCreateSerializer(serializers.ModelSerializer):
    """Serializer for posting a new customer request"""

    class Meta:
        model = Request
        fields = ['need', 'category', 'location', 'budget', 'deadline', 'description', 'allow_contact']

    def validate_need(self, value):
        if not value or len(value.strip()) < 3:
            raise serializers.ValidationError("Please describe what you need.")
        return value.strip()

    def validate_description(self, value):
        if not value or len(value.strip()) < 10:
            raise serializers.ValidationError("Please add a bit more detail (at least 10 characters).")
        return value.strip()


class RequestListSerializer(serializers.ModelSerializer):
    """A requester's own request, with nested responses — for My Requests"""
    category_name = serializers.CharField(source='category.name', read_only=True, allow_null=True)
    effective_status = serializers.SerializerMethodField()
    responses = RequestResponseSerializer(many=True, read_only=True)
    response_count = serializers.SerializerMethodField()

    class Meta:
        model = Request
        fields = [
            'id', 'need', 'category', 'category_name', 'location', 'budget', 'deadline',
            'description', 'allow_contact', 'status', 'effective_status',
            'responses', 'response_count', 'created_at',
        ]

    def get_effective_status(self, obj):
        return obj.effective_status()

    def get_response_count(self, obj):
        return obj.responses.count()


class OwnerRequestListSerializer(serializers.ModelSerializer):
    """A customer request as seen by a business deciding whether to respond"""
    category_name = serializers.CharField(source='category.name', read_only=True, allow_null=True)
    requester_name = serializers.SerializerMethodField()
    already_responded = serializers.SerializerMethodField()

    class Meta:
        model = Request
        fields = [
            'id', 'need', 'category', 'category_name', 'location', 'budget', 'deadline',
            'description', 'allow_contact', 'requester_name', 'already_responded', 'created_at',
        ]

    def get_requester_name(self, obj):
        return obj.user.get_full_name() or obj.user.email

    def get_already_responded(self, obj):
        business_id = self.context.get('business_id')
        if not business_id:
            return False
        return obj.responses.filter(business_id=business_id).exists()


class RequestResponseCreateSerializer(serializers.ModelSerializer):
    """Serializer for a business responding to a customer request"""

    class Meta:
        model = RequestResponse
        fields = ['message']

    def validate_message(self, value):
        if not value or len(value.strip()) < 5:
            raise serializers.ValidationError("Please write a short response.")
        return value.strip()


# ==================== Campaigns (Promote) ====================

class CampaignCreateSerializer(serializers.ModelSerializer):
    """Serializer for a business owner submitting a promotion request"""

    class Meta:
        model = Campaign
        fields = ['content_title', 'goal', 'location', 'budget', 'duration_days', 'post', 'offer', 'placement_type']

    def validate_content_title(self, value):
        if not value or not value.strip():
            raise serializers.ValidationError("Please describe what you're promoting.")
        return value.strip()

    def validate_budget(self, value):
        if value <= 0:
            raise serializers.ValidationError("Budget must be greater than zero.")
        return value

    def validate(self, attrs):
        placement_type = attrs.get('placement_type', 'boost')
        if placement_type == 'featured_offer' and not attrs.get('offer'):
            raise serializers.ValidationError({'offer': 'Select an offer to feature.'})
        return attrs


class CampaignSerializer(serializers.ModelSerializer):
    """Read serializer — used by both the business owner's Promote page and admin's Ads & Promotions"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    placement_type_display = serializers.CharField(source='get_placement_type_display', read_only=True)
    impressions = serializers.SerializerMethodField()
    reach = serializers.SerializerMethodField()
    clicks = serializers.SerializerMethodField()
    spend = serializers.SerializerMethodField()
    cost_per_lead = serializers.SerializerMethodField()

    class Meta:
        model = Campaign
        fields = [
            'id', 'business', 'business_name', 'post', 'offer', 'placement_type', 'placement_type_display',
            'content_title', 'goal', 'location', 'budget', 'duration_days', 'status', 'status_display',
            'admin_note', 'activated_at', 'created_at',
            'impressions', 'reach', 'clicks', 'spend', 'cost_per_lead',
        ]

    def get_impressions(self, obj):
        return obj.events.filter(event_type='impression').count()

    def get_reach(self, obj):
        return obj.events.filter(event_type='impression').exclude(session_id='').values('session_id').distinct().count()

    def get_clicks(self, obj):
        return obj.events.filter(event_type='click').count()

    def get_spend(self, obj):
        """Real per-event spend — see utils.compute_campaign_spend."""
        from .utils import compute_campaign_spend
        return float(compute_campaign_spend(obj))

    def get_cost_per_lead(self, obj):
        clicks = self.get_clicks(obj)
        if not clicks:
            return None
        return round(self.get_spend(obj) / clicks, 2)


class PlanSerializer(serializers.ModelSerializer):
    class Meta:
        model = Plan
        fields = ['id', 'slug', 'name', 'price', 'currency', 'period', 'tagline', 'features', 'is_highlighted', 'is_self_serve']


class SubscriptionSerializer(serializers.ModelSerializer):
    plan = PlanSerializer(read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Subscription
        fields = ['id', 'plan', 'status', 'status_display', 'current_period_end', 'updated_at']


class PaymentSerializer(serializers.ModelSerializer):
    # A plain `source='plan.name'` CharField would blow up on campaign
    # payments (`plan` is null there) — SerializerMethodField sidesteps that
    # by handling both purposes explicitly instead of relying on DRF's
    # dotted-source null handling.
    plan_name = serializers.SerializerMethodField()
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Payment
        fields = ['id', 'purpose', 'plan_name', 'tx_ref', 'amount', 'currency', 'status', 'status_display', 'created_at', 'verified_at']

    def get_plan_name(self, obj):
        if obj.plan_id:
            return obj.plan.name
        if obj.campaign_id:
            return f'Campaign: {obj.campaign.content_title}'
        return None


class AdminSubscriptionSerializer(serializers.ModelSerializer):
    """Read serializer for admin-app's Billing console"""
    business_name = serializers.CharField(source='business.title', read_only=True)
    business_id = serializers.IntegerField(source='business.id', read_only=True)
    plan = PlanSerializer(read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Subscription
        fields = ['id', 'business_id', 'business_name', 'plan', 'status', 'status_display', 'current_period_end', 'updated_at']


class AuditLogSerializer(serializers.ModelSerializer):
    """Read serializer for admin-app's Audit Logs console"""
    actor_email = serializers.EmailField(source='actor.email', read_only=True, allow_null=True)

    class Meta:
        model = AuditLog
        fields = ['id', 'actor_email', 'action', 'target_type', 'target_id', 'target_repr', 'metadata', 'created_at']


class PlatformSettingsSerializer(serializers.ModelSerializer):
    class Meta:
        model = PlatformSettings
        fields = [
            'allow_new_signups', 'allow_new_businesses', 'maintenance_mode',
            'maintenance_message', 'support_email', 'support_phone',
            'cost_per_impression', 'cost_per_click', 'updated_at',
        ]
        read_only_fields = ['updated_at']
