import re
import time
import base64

from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.db import transaction
from django.db.models import Q

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.tokens import RefreshToken

from .models import Profiles
from django.contrib.auth.hashers import make_password



from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from django.core.exceptions import ObjectDoesNotExist
from rest_framework_simplejwt.tokens import RefreshToken
import re  # For basic email validation
# from twilio.rest import Client as TwilioClient # 💡 Maru Peyaridhal!
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from rest_framework.permissions import AllowAny, IsAuthenticated
from .models import (
    Property,
    PropertyImage,
    PropertyVideo,
    PropertyDocument,
    BuyerEnquiry,
    SellerEnquiry,
    SellerEnquiryPhoto,
    SellerEnquiryVideo,
    SellerEnquiryDocument,
)
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
# from .models import Profiles  # uncomment / adjust import to match your app
TWO_PLACES = Decimal('0.01')


def ok(data=None, message=None, code=status.HTTP_200_OK):
    return Response({
        "status": {"code": code, "response": "success"},
        "error": None,
        **({"message": message} if message else {}),
        "data": data,
    }, status=code)


def fail(message, code=status.HTTP_400_BAD_REQUEST):
    return Response({
        "status": {"code": code, "response": "failed"},
        "error": True,
        "message": message,
    }, status=code)


def to_decimal(value, field_name):
    """
    Validate + coerce a value into a Decimal, raising a clear message on bad
    input. Goes through str() first so binary floating-point artifacts
    (e.g. 0.1 + 0.2 != 0.3) never leak into money fields.
    """
    if value is None or value == '':
        raise ValueError(f"'{field_name}' is required.")
    try:
        return Decimal(str(value))
    except (InvalidOperation, ValueError, TypeError):
        raise ValueError(f"'{field_name}' must be a valid number.")


def q2(value):
    """Round a Decimal to exactly 2 places using standard rounding (not banker's)."""
    return Decimal(value).quantize(TWO_PLACES, rounding=ROUND_HALF_UP)


# ============================================================ LOGIN =======
class LoginAPIView(APIView):
    """
    Accepts either a username or an email in `username`, plus `password`.
    `fcm_token` (optional) is stored against the profile for push notifications —
    it is intentionally NOT written into `pincode`; that was a bug in the
    previous version. Adjust the field name below to match your Profile model.
    """

    def post(self, request):
        data = request.data
        username_or_email = (data.get("username") or "").strip()
        password = data.get("password")
        fcm_token = data.get("fcm_token")

        if not username_or_email or not password:
            return fail("Username/email and password are required.", status.HTTP_400_BAD_REQUEST)

        is_email = re.match(r"[^@]+@[^@]+\.[^@]+", username_or_email)

        if is_email:
            try:
                matched = User.objects.get(email__iexact=username_or_email)
                username_to_auth = matched.username
            except User.DoesNotExist:
                return fail("Invalid username or password.", status.HTTP_401_UNAUTHORIZED)
        else:
            username_to_auth = username_or_email

        user = authenticate(request, username=username_to_auth, password=password)

        if user is None:
            return fail("Invalid username or password.", status.HTTP_401_UNAUTHORIZED)

        if not user.is_active:
            return fail("This account has been disabled.", status.HTTP_403_FORBIDDEN)

        login(request, user)
        token = RefreshToken.for_user(user)

        profile_photo = None
        phone = None
        role = None

        # Wire this up to your actual Profile model / related_name.
        # Example:
        try:
            profile = Profiles.objects.get(user_id=user.id)
            if fcm_token:
                profile.fcm_token = fcm_token
                profile.save(update_fields=["fcm_token"])
            profile_photo = request.build_absolute_uri(profile.profiles.url) if profile.profiles else None
            phone = profile.phone
            role = profile.role
        except Profiles.DoesNotExist:
            pass

        return ok({
            "name": user.username,
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "isSuper": user.is_superuser,
            "refresh": str(token),
            "token": str(token.access_token),
            "profile": profile_photo,
            "companyname": "loop",
            "phone": phone,
            "role": role,
        }, message="Login success")


# ---------------------------------------------------------------------
# Shared response helpers — every endpoint in this file replies through
# these two, so the envelope is identical everywhere:
#   { "status": {...}, "error": ..., "message": ..., "data": ... }
# ---------------------------------------------------------------------
 
def ok(data=None, message="Success", code=status.HTTP_200_OK):
    return Response({
        "status": {"code": code, "response": "success"},
        "error": None,
        "message": message,
        "data": data,
    }, status=code)
 
 
def fail(message, code=status.HTTP_400_BAD_REQUEST, data=None):
    return Response({
        "status": {"code": code, "response": "failed"},
        "error": True,
        "message": message,
        "data": data,
    }, status=code)
 
 
def is_admin_user(user):
    """Matches the role convention used in LoginAPIView (Profiles.role).
    Adjust the role value below if your project uses a different number
    for "admin"."""
    if not (user and user.is_authenticated):
        return False
    if user.is_superuser or user.is_staff:
        return True
    try:
        profile = Profiles.objects.get(user_id=user.id)
        return profile.role == 1
    except Exception:
        return False
 
 
def build_file_url(request, field):
    if not field:
        return None
    try:
        return request.build_absolute_uri(field.url)
    except Exception:
        return None
 
 
# ---------------------------------------------------------------------
# Upload validation — rejecting a bad file up front with a clear message
# is what actually fixes "it looks like nothing happened"/"video won't
# play" complaints: without this, an unsupported file type (e.g. a .mov
# or .avi video no browser can play inline, or a 300MB file silently
# dropped by Django's upload size limit) saves with no feedback at all.
# ---------------------------------------------------------------------
 
IMAGE_EXTENSIONS = {"jpg", "jpeg", "png", "webp", "gif"}
VIDEO_EXTENSIONS = {"mp4", "webm", "ogg"}            # formats every major browser can play inline
DOCUMENT_EXTENSIONS = {"pdf", "doc", "docx"}
 
MAX_IMAGE_MB = 10
MAX_VIDEO_MB = 200
MAX_DOCUMENT_MB = 20
 
 
MOBILE_RE = re.compile(r"^\+?\d{10,13}$")
EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
 
 
def validate_mobile(value):
    if not value or not MOBILE_RE.match(value.replace(" ", "")):
        return "Enter a valid mobile number (10-13 digits)."
    return None
 
 
def validate_email_format(value):
    if value and not EMAIL_RE.match(value):
        return "Enter a valid email address."
    return None
 
 
def validate_upload(f, allowed_extensions, max_mb, label):
    """Returns an error string, or None if the file is acceptable."""
    ext = f.name.rsplit(".", 1)[-1].lower() if "." in f.name else ""
    if ext not in allowed_extensions:
        return (f"'{f.name}' is not a supported {label} format. "
                f"Allowed: {', '.join(sorted(allowed_extensions))}.")
    size_mb = f.size / (1024 * 1024)
    if size_mb > max_mb:
        return f"'{f.name}' is {size_mb:.1f}MB — {label} files must be under {max_mb}MB."
    return None
 
 
def copy_django_file(file_field):
    """Reads an existing uploaded file and returns a ContentFile so it can
    be saved onto a different model's FileField/ImageField — used when a
    seller's submitted photos/videos/documents are copied onto the live
    Property listing at approval time."""
    if not file_field:
        return None
    file_field.open('rb')
    try:
        content = file_field.read()
    finally:
        file_field.close()
    name = file_field.name.rsplit('/', 1)[-1]
    return ContentFile(content, name=name)
 
 
# ============================================================ LOGIN =======
class LoginAPIView(APIView):
    """
    Accepts either a username or an email in `username`, plus `password`.
    `fcm_token` (optional) is stored against the profile for push notifications.
    """
    permission_classes = [AllowAny]
 
    def post(self, request):
        data = request.data
        username_or_email = (data.get("username") or "").strip()
        password = data.get("password")
        fcm_token = data.get("fcm_token")
 
        if not username_or_email or not password:
            return fail("Username/email and password are required.", status.HTTP_400_BAD_REQUEST)
 
        is_email = re.match(r"[^@]+@[^@]+\.[^@]+", username_or_email)
 
        if is_email:
            try:
                matched = User.objects.get(email__iexact=username_or_email)
                username_to_auth = matched.username
            except User.DoesNotExist:
                return fail("Invalid username or password.", status.HTTP_401_UNAUTHORIZED)
        else:
            username_to_auth = username_or_email
 
        user = authenticate(request, username=username_to_auth, password=password)
 
        if user is None:
            return fail("Invalid username or password.", status.HTTP_401_UNAUTHORIZED)
 
        if not user.is_active:
            return fail("This account has been disabled.", status.HTTP_403_FORBIDDEN)
 
        login(request, user)
        token = RefreshToken.for_user(user)
 
        profile_photo = None
        phone = None
        role = None
 
        try:
            profile = Profiles.objects.get(user_id=user.id)
            if fcm_token:
                profile.fcm_token = fcm_token
                profile.save(update_fields=["fcm_token"])
            profile_photo = request.build_absolute_uri(profile.profiles.url) if profile.profiles else None
            phone = profile.phone
            role = profile.role
        except Profiles.DoesNotExist:
            pass
 
        return ok({
            "name": user.username,
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "isSuper": user.is_superuser,
            "refresh": str(token),
            "token": str(token.access_token),
            "profile": profile_photo,
            "companyname": "loop",
            "phone": phone,
            "role": role,
        }, message="Login success")
 
 
# ---------------------------------------------------------------------
# Property
# ---------------------------------------------------------------------
 
class PropertyAPIView(APIView):
    """
    GET    /api/v1/property/        -> list (search, place_name, property_type, featured, status)
    GET    /api/v1/property/<id>/   -> single property with images/videos/documents
    POST   /api/v1/property/        -> create (admin only)
    PUT    /api/v1/property/<id>/   -> update (admin only)
    DELETE /api/v1/property/<id>/   -> delete (admin only)
    """
    permission_classes = [AllowAny]
    parser_classes = [MultiPartParser, FormParser, JSONParser]
 
    def get_property_data(self, request, prop, detailed=False):
        images = prop.images.filter(status=1).order_by('order', 'id')
        data = {
            'id': prop.id,
            'title': prop.title,
            'place_name': prop.place_name,
            'district': prop.district,
            'property_type': prop.property_type,
            'land_area': prop.land_area,
            'price': str(prop.price) if prop.price is not None else None,
            'price_display': prop.price_display,
            'short_description': prop.short_description,
            'is_featured': prop.is_featured,
            'status': prop.status,
            'created_at': prop.created_at,
            'cover_image': build_file_url(request, images.first().image) if images.first() else None,
        }
 
        if detailed:
            data.update({
                'full_address': prop.full_address,
                'map_link': prop.map_link,
                'description': prop.description,
                'updated_at': prop.updated_at,
                'images': [
                    {'id': im.id, 'image': build_file_url(request, im.image), 'caption': im.caption, 'is_cover': im.is_cover, 'order': im.order}
                    for im in images
                ],
                'videos': [
                    {'id': v.id, 'video': build_file_url(request, v.video), 'video_url': v.video_url, 'title': v.title, 'order': v.order}
                    for v in prop.videos.filter(status=1).order_by('order', 'id')
                ],
                'documents': [
                    {'id': d.id, 'document': build_file_url(request, d.document), 'title': d.title, 'order': d.order}
                    for d in prop.documents.filter(status=1).order_by('order', 'id')
                ],
            })
        return data
 
    def get(self, request, *args, **kwargs):
        id = kwargs.get('id')
 
        if id is not None:
            try:
                prop = Property.objects.get(id=id)
            except ObjectDoesNotExist:
                return fail("Property not found", status.HTTP_404_NOT_FOUND)
            return ok(self.get_property_data(request, prop, detailed=True))
 
        search = request.query_params.get('search', '').strip()
        place_name = request.query_params.get('place_name', '').strip()
        property_type = request.query_params.get('property_type', '').strip()
        featured = request.query_params.get('featured', '').strip()
        status_param = request.query_params.get('status', '').strip()
 
        properties = Property.objects.all().order_by('place_name', '-created_at')
 
        if is_admin_user(request.user):
            if status_param:
                try:
                    properties = properties.filter(status=int(status_param))
                except ValueError:
                    pass
        else:
            properties = properties.filter(status=1)
 
        if search:
            properties = properties.filter(
                Q(place_name__icontains=search) | Q(district__icontains=search) |
                Q(title__icontains=search) | Q(full_address__icontains=search)
            )
        if place_name:
            properties = properties.filter(place_name__iexact=place_name)
        if property_type:
            properties = properties.filter(property_type=property_type)
        if featured == '1':
            properties = properties.filter(is_featured=1)
 
        return ok([self.get_property_data(request, p) for p in properties])
 
    def post(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized to add a property", status.HTTP_403_FORBIDDEN)
 
        data = request.data
        try:
            title = data.get("title")
            place_name = data.get("place_name")
            land_area = data.get("land_area")
 
            if not title or not place_name or not land_area:
                return fail("title, place_name and land_area are required", status.HTTP_400_BAD_REQUEST)
 
            raw_price = data.get("price")
            if raw_price not in (None, ""):
                try:
                    if float(raw_price) <= 0:
                        return fail("Price must be a positive number.", status.HTTP_400_BAD_REQUEST)
                except (TypeError, ValueError):
                    return fail("Price must be a valid number.", status.HTTP_400_BAD_REQUEST)
 
            prop = Property(
                user=request.user,
                title=title,
                place_name=place_name,
                district=data.get("district"),
                full_address=data.get("full_address"),
                map_link=data.get("map_link"),
                property_type=data.get("property_type"),
                land_area=land_area,
                price=data.get("price") or None,
                price_display=data.get("price_display"),
                description=data.get("description"),
                short_description=data.get("short_description"),
                is_featured=1 if str(data.get("is_featured")) in ("1", "true", "True") else 0,
                status=1 if str(data.get("status", "1")) in ("1", "true", "True") else 0,
            )
            prop.save()
 
            return ok(self.get_property_data(request, prop, detailed=True),
                       message="Property added successfully", code=status.HTTP_201_CREATED)
 
        except Exception as e:
            return fail(f"An error occurred: {str(e)}", status.HTTP_500_INTERNAL_SERVER_ERROR)
 
    def put(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized to update this property", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        data = request.data
        try:
            prop = Property.objects.get(id=id)
        except ObjectDoesNotExist:
            return fail("Property not found", status.HTTP_404_NOT_FOUND)
 
        fields = [
            "title", "place_name", "district", "full_address", "map_link",
            "property_type", "land_area", "price_display", "description", "short_description",
        ]
        for field in fields:
            if field in data:
                setattr(prop, field, data.get(field))
 
        if "price" in data:
            raw_price = data.get("price")
            if raw_price not in (None, ""):
                try:
                    if float(raw_price) <= 0:
                        return fail("Price must be a positive number.", status.HTTP_400_BAD_REQUEST)
                except (TypeError, ValueError):
                    return fail("Price must be a valid number.", status.HTTP_400_BAD_REQUEST)
            prop.price = raw_price or None
        if "is_featured" in data:
            prop.is_featured = 1 if str(data.get("is_featured")) in ("1", "true", "True") else 0
        if "status" in data:
            prop.status = 1 if str(data.get("status")) in ("1", "true", "True") else 0
 
        prop.save()
        return ok(self.get_property_data(request, prop, detailed=True), message="Property updated successfully")
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized to delete this property", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            prop = Property.objects.get(id=id)
        except ObjectDoesNotExist:
            return fail("Property not found", status.HTTP_404_NOT_FOUND)
 
        prop.delete()
        return ok(None, message="Property deleted successfully")
 
 
class PropertyLocationAPIView(APIView):
    """GET /api/v1/property-location/ -> distinct active place names, alphabetically."""
    permission_classes = [AllowAny]
 
    def get(self, request, *args, **kwargs):
        names = (
            Property.objects.filter(status=1)
            .exclude(place_name__isnull=True).exclude(place_name="")
            .values_list('place_name', flat=True)
        )
        unique_sorted = sorted(set(names), key=lambda s: s.lower())
        return ok(unique_sorted)
 
 
class DashboardSummaryAPIView(APIView):
    """GET /api/v1/dashboard-summary/ -> counts for the admin dashboard (admin only)."""
    permission_classes = [AllowAny]
 
    def get(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        data = {
            "total_properties": Property.objects.count(),
            "active_properties": Property.objects.filter(status=1).count(),
            "featured_properties": Property.objects.filter(is_featured=1).count(),
            "total_buyer_enquiries": BuyerEnquiry.objects.count(),
            "new_buyer_enquiries": BuyerEnquiry.objects.filter(status=1).count(),
            "total_seller_enquiries": SellerEnquiry.objects.count(),
            "new_seller_enquiries": SellerEnquiry.objects.filter(status=1).count(),
            "pending_seller_approvals": SellerEnquiry.objects.exclude(status=5).count(),
        }
        return ok(data)
 
 
# ---------------------------------------------------------------------
# Property media (images / videos / documents)
# ---------------------------------------------------------------------
 
class PropertyImageAPIView(APIView):
    """
    POST   /api/v1/property-image/        -> upload (form fields: property, images[] files) — admin only
    DELETE /api/v1/property-image/<id>/   -> remove one image — admin only
    """
    permission_classes = [AllowAny]
    parser_classes = [MultiPartParser, FormParser]
 
    def post(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        property_id = request.data.get("property")
        files = request.FILES.getlist("images")
 
        try:
            prop = Property.objects.get(id=property_id)
        except ObjectDoesNotExist:
            return fail("Property not found", status.HTTP_404_NOT_FOUND)
 
        if not files:
            return fail("No images provided", status.HTTP_400_BAD_REQUEST)
 
        for f in files:
            error = validate_upload(f, IMAGE_EXTENSIONS, MAX_IMAGE_MB, "image")
            if error:
                return fail(error, status.HTTP_400_BAD_REQUEST)
 
        created = []
        for f in files:
            img = PropertyImage.objects.create(property=prop, image=f)
            created.append({'id': img.id, 'image': build_file_url(request, img.image)})
 
        return ok(created, message="Images uploaded successfully", code=status.HTTP_201_CREATED)
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            PropertyImage.objects.get(id=id).delete()
        except ObjectDoesNotExist:
            return fail("Image not found", status.HTTP_404_NOT_FOUND)
        return ok(None, message="Image deleted successfully")
 
 
class PropertyVideoAPIView(APIView):
    """
    POST   /api/v1/property-video/        -> upload (form fields: property, videos[] files, video_url) — admin only
    DELETE /api/v1/property-video/<id>/   -> remove one video — admin only
    """
    permission_classes = [AllowAny]
    parser_classes = [MultiPartParser, FormParser]
 
    def post(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        property_id = request.data.get("property")
        files = request.FILES.getlist("videos")
        video_url = request.data.get("video_url")
 
        try:
            prop = Property.objects.get(id=property_id)
        except ObjectDoesNotExist:
            return fail("Property not found", status.HTTP_404_NOT_FOUND)
 
        for f in files:
            error = validate_upload(f, VIDEO_EXTENSIONS, MAX_VIDEO_MB, "video")
            if error:
                return fail(error, status.HTTP_400_BAD_REQUEST)
 
        created = []
        for f in files:
            v = PropertyVideo.objects.create(property=prop, video=f)
            created.append({'id': v.id, 'video': build_file_url(request, v.video)})
        if video_url:
            v = PropertyVideo.objects.create(property=prop, video_url=video_url)
            created.append({'id': v.id, 'video_url': v.video_url})
 
        if not created:
            return fail("No videos provided", status.HTTP_400_BAD_REQUEST)
 
        return ok(created, message="Videos uploaded successfully", code=status.HTTP_201_CREATED)
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            PropertyVideo.objects.get(id=id).delete()
        except ObjectDoesNotExist:
            return fail("Video not found", status.HTTP_404_NOT_FOUND)
        return ok(None, message="Video deleted successfully")
 
 
class PropertyDocumentAPIView(APIView):
    """
    POST   /api/v1/property-document/        -> upload (form fields: property, documents[] files) — admin only
    DELETE /api/v1/property-document/<id>/   -> remove one document — admin only
    """
    permission_classes = [AllowAny]
    parser_classes = [MultiPartParser, FormParser]
 
    def post(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        property_id = request.data.get("property")
        files = request.FILES.getlist("documents")
 
        try:
            prop = Property.objects.get(id=property_id)
        except ObjectDoesNotExist:
            return fail("Property not found", status.HTTP_404_NOT_FOUND)
 
        if not files:
            return fail("No documents provided", status.HTTP_400_BAD_REQUEST)
 
        for f in files:
            error = validate_upload(f, DOCUMENT_EXTENSIONS, MAX_DOCUMENT_MB, "document")
            if error:
                return fail(error, status.HTTP_400_BAD_REQUEST)
 
        created = []
        for f in files:
            d = PropertyDocument.objects.create(property=prop, document=f)
            created.append({'id': d.id, 'document': build_file_url(request, d.document)})
 
        return ok(created, message="Documents uploaded successfully", code=status.HTTP_201_CREATED)
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            PropertyDocument.objects.get(id=id).delete()
        except ObjectDoesNotExist:
            return fail("Document not found", status.HTTP_404_NOT_FOUND)
        return ok(None, message="Document deleted successfully")
 
 
# ---------------------------------------------------------------------
# Buyer enquiry
# ---------------------------------------------------------------------
 
class BuyerEnquiryAPIView(APIView):
    """
    GET    /api/v1/buyer-enquiry/        -> list, admin only (filter by ?status=)
    GET    /api/v1/buyer-enquiry/<id>/   -> single, admin only
    POST   /api/v1/buyer-enquiry/        -> public — buyer submits a requirement
    PUT    /api/v1/buyer-enquiry/<id>/   -> update status / admin_notes, admin only
    DELETE /api/v1/buyer-enquiry/<id>/   -> delete, admin only
    """
    permission_classes = [AllowAny]
 
    def get_data(self, enquiry):
        return {
            'id': enquiry.id,
            'full_name': enquiry.full_name,
            'mobile_number': enquiry.mobile_number,
            'email': enquiry.email,
            'preferred_location': enquiry.preferred_location,
            'property_type': enquiry.property_type,
            'budget': enquiry.budget,
            'message': enquiry.message,
            'property_id': enquiry.property_id,
            'property_title': enquiry.property.title if enquiry.property_id else None,
            'status': enquiry.status,
            'admin_notes': enquiry.admin_notes,
            'created_at': enquiry.created_at,
        }
 
    def get(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        if id is not None:
            try:
                enquiry = BuyerEnquiry.objects.get(id=id)
            except ObjectDoesNotExist:
                return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
            return ok(self.get_data(enquiry))
 
        status_param = request.query_params.get('status', '').strip()
        enquiries = BuyerEnquiry.objects.all().order_by('-created_at')
        if status_param:
            try:
                enquiries = enquiries.filter(status=int(status_param))
            except ValueError:
                pass
 
        return ok([self.get_data(e) for e in enquiries])
 
    def post(self, request, *args, **kwargs):
        data = request.data
        try:
            full_name = data.get("full_name")
            mobile_number = data.get("mobile_number")
 
            if not full_name or not mobile_number:
                return fail("full_name and mobile_number are required", status.HTTP_400_BAD_REQUEST)
 
            error = validate_mobile(mobile_number) or validate_email_format(data.get("email"))
            if error:
                return fail(error, status.HTTP_400_BAD_REQUEST)
 
            property_obj = None
            if data.get("property"):
                try:
                    property_obj = Property.objects.get(id=data.get("property"))
                except ObjectDoesNotExist:
                    property_obj = None
 
            enquiry = BuyerEnquiry.objects.create(
                full_name=full_name,
                mobile_number=mobile_number,
                email=data.get("email"),
                preferred_location=data.get("preferred_location"),
                property_type=data.get("property_type"),
                budget=data.get("budget"),
                message=data.get("message"),
                property=property_obj,
            )
 
            return ok(self.get_data(enquiry),
                       message="Thank you! Your enquiry has been submitted successfully.",
                       code=status.HTTP_201_CREATED)
 
        except Exception as e:
            return fail(f"An error occurred: {str(e)}", status.HTTP_500_INTERNAL_SERVER_ERROR)
 
    def put(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        data = request.data
        try:
            enquiry = BuyerEnquiry.objects.get(id=id)
        except ObjectDoesNotExist:
            return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
 
        if "status" in data:
            enquiry.status = data.get("status")
        if "admin_notes" in data:
            enquiry.admin_notes = data.get("admin_notes")
        enquiry.save()
 
        return ok(self.get_data(enquiry), message="Enquiry updated successfully")
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            BuyerEnquiry.objects.get(id=id).delete()
        except ObjectDoesNotExist:
            return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
        return ok(None, message="Enquiry deleted successfully")
 
 
# ---------------------------------------------------------------------
# Seller enquiry
# ---------------------------------------------------------------------
 
@transaction.atomic
def approve_seller_enquiry(request, enquiry):
    """Converts an approved seller submission into a live Property listing,
    copying across any photos/videos/documents the seller uploaded."""
    prop = Property.objects.create(
        user=request.user,
        title=enquiry.property_name,
        place_name=enquiry.location,
        district=enquiry.location,
        property_type=enquiry.property_type,
        land_area=enquiry.land_area,
        price=None,
        price_display=enquiry.expected_price,
        description=enquiry.description or enquiry.additional_info,
        short_description=(enquiry.description or enquiry.additional_info or '')[:280],
        is_featured=0,
        status=1,
    )
 
    for photo in enquiry.photos.all():
        copied = copy_django_file(photo.image)
        if copied:
            PropertyImage.objects.create(property=prop, image=copied)
 
    for video in enquiry.videos.all():
        copied = copy_django_file(video.video)
        if copied:
            PropertyVideo.objects.create(property=prop, video=copied)
 
    for doc in enquiry.documents.all():
        copied = copy_django_file(doc.document)
        if copied:
            PropertyDocument.objects.create(property=prop, document=copied)
 
    enquiry.status = 5  # Approved & Listed
    note = f"Approved and published as property #{prop.id}."
    enquiry.admin_notes = f"{enquiry.admin_notes}\n{note}".strip() if enquiry.admin_notes else note
    enquiry.save()
 
    return prop
 
 
class SellerEnquiryAPIView(APIView):
    """
    GET    /api/v1/seller-enquiry/                 -> list, admin only (filter by ?status=)
    GET    /api/v1/seller-enquiry/<id>/             -> single, admin only
    POST   /api/v1/seller-enquiry/                  -> public — seller submits property details
                                                        (multipart: photos[], videos[], documents[])
    PUT    /api/v1/seller-enquiry/<id>/             -> update status / admin_notes, admin only
    PUT    /api/v1/seller-enquiry/<id>/?val=approve -> approve & publish as a live Property, admin only
    DELETE /api/v1/seller-enquiry/<id>/             -> delete, admin only
    """
    permission_classes = [AllowAny]
    parser_classes = [MultiPartParser, FormParser, JSONParser]
 
    def get_data(self, request, enquiry):
        return {
            'id': enquiry.id,
            'seller_name': enquiry.seller_name,
            'mobile_number': enquiry.mobile_number,
            'email': enquiry.email,
            'property_name': enquiry.property_name,
            'location': enquiry.location,
            'property_type': enquiry.property_type,
            'land_area': enquiry.land_area,
            'expected_price': enquiry.expected_price,
            'description': enquiry.description,
            'additional_info': enquiry.additional_info,
            'status': enquiry.status,
            'admin_notes': enquiry.admin_notes,
            'created_at': enquiry.created_at,
            'photos': [{'id': p.id, 'image': build_file_url(request, p.image)} for p in enquiry.photos.all()],
            'videos': [{'id': v.id, 'video': build_file_url(request, v.video)} for v in enquiry.videos.all()],
            'documents': [{'id': d.id, 'document': build_file_url(request, d.document)} for d in enquiry.documents.all()],
        }
 
    def get(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        if id is not None:
            try:
                enquiry = SellerEnquiry.objects.get(id=id)
            except ObjectDoesNotExist:
                return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
            return ok(self.get_data(request, enquiry))
 
        status_param = request.query_params.get('status', '').strip()
        enquiries = SellerEnquiry.objects.all().order_by('-created_at')
        if status_param:
            try:
                enquiries = enquiries.filter(status=int(status_param))
            except ValueError:
                pass
 
        return ok([self.get_data(request, e) for e in enquiries])
 
    def post(self, request, *args, **kwargs):
        data = request.data
        try:
            seller_name = data.get("seller_name")
            mobile_number = data.get("mobile_number")
            property_name = data.get("property_name")
            location = data.get("location")
 
            if not seller_name or not mobile_number or not property_name or not location:
                return fail("seller_name, mobile_number, property_name and location are required",
                            status.HTTP_400_BAD_REQUEST)
 
            error = validate_mobile(mobile_number) or validate_email_format(data.get("email"))
            if error:
                return fail(error, status.HTTP_400_BAD_REQUEST)
 
            photos = request.FILES.getlist("photos")
            videos = request.FILES.getlist("videos")
            documents = request.FILES.getlist("documents")
 
            # Validate every file up front — before creating anything —
            # so a bad file fails loudly instead of silently dropping
            # mid-way through the submission.
            for f in photos:
                error = validate_upload(f, IMAGE_EXTENSIONS, MAX_IMAGE_MB, "image")
                if error:
                    return fail(error, status.HTTP_400_BAD_REQUEST)
            for f in videos:
                error = validate_upload(f, VIDEO_EXTENSIONS, MAX_VIDEO_MB, "video")
                if error:
                    return fail(error, status.HTTP_400_BAD_REQUEST)
            for f in documents:
                error = validate_upload(f, DOCUMENT_EXTENSIONS, MAX_DOCUMENT_MB, "document")
                if error:
                    return fail(error, status.HTTP_400_BAD_REQUEST)
 
            enquiry = SellerEnquiry.objects.create(
                seller_name=seller_name,
                mobile_number=mobile_number,
                email=data.get("email"),
                property_name=property_name,
                location=location,
                property_type=data.get("property_type"),
                land_area=data.get("land_area"),
                expected_price=data.get("expected_price"),
                description=data.get("description"),
                additional_info=data.get("additional_info"),
            )
 
            for f in photos:
                SellerEnquiryPhoto.objects.create(seller_enquiry=enquiry, image=f)
            for f in videos:
                SellerEnquiryVideo.objects.create(seller_enquiry=enquiry, video=f)
            for f in documents:
                SellerEnquiryDocument.objects.create(seller_enquiry=enquiry, document=f)
 
            return ok(self.get_data(request, enquiry),
                       message="Thank you! Your property details have been submitted successfully.",
                       code=status.HTTP_201_CREATED)
 
        except Exception as e:
            return fail(f"An error occurred: {str(e)}", status.HTTP_500_INTERNAL_SERVER_ERROR)
 
    def put(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        data = request.data
        val = request.query_params.get('val')
 
        try:
            enquiry = SellerEnquiry.objects.get(id=id)
        except ObjectDoesNotExist:
            return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
 
        if val == 'approve':
            if enquiry.status == 5:
                return fail("This submission has already been approved and published.", status.HTTP_400_BAD_REQUEST)
            try:
                prop = approve_seller_enquiry(request, enquiry)
            except Exception as e:
                return fail(f"Could not publish this property: {str(e)}", status.HTTP_500_INTERNAL_SERVER_ERROR)
 
            result = self.get_data(request, enquiry)
            result['property_id'] = prop.id
            return ok(result, message="Approved! The property is now live on the website.")
 
        if "status" in data:
            enquiry.status = data.get("status")
        if "admin_notes" in data:
            enquiry.admin_notes = data.get("admin_notes")
        enquiry.save()
 
        return ok(self.get_data(request, enquiry), message="Enquiry updated successfully")
 
    def delete(self, request, *args, **kwargs):
        if not is_admin_user(request.user):
            return fail("You are not authorized", status.HTTP_403_FORBIDDEN)
 
        id = kwargs.get('id')
        try:
            SellerEnquiry.objects.get(id=id).delete()
        except ObjectDoesNotExist:
            return fail("Enquiry not found", status.HTTP_404_NOT_FOUND)
        return ok(None, message="Enquiry deleted successfully")
 