from rest_framework import serializers

from .models import (
    AccessCard,
    AccessLog,
    AccessPoint,
    Equipment,
    EquipmentCategory,
    FacilityBooking,
    GiftCard,
    GymDoorQR,
    MaintenanceLog,
    POSTransaction,
    POSTransactionItem,
    Product,
    PurchaseOrder,
    PurchaseOrderItem,
    Supplier,
    TimeBasedAccessRule,
    Visitor,
)


# ---------------------------------------------------------------------------
# Visitor serializers
# ---------------------------------------------------------------------------


class VisitorSerializer(serializers.ModelSerializer):
    visitor_code = serializers.CharField(read_only=True)

    class Meta:
        model = Visitor
        fields = [
            "id",
            "name",
            "phone",
            "visitor_code",
            "location",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["id", "visitor_code", "created_at"]


class VisitorLookupSerializer(serializers.Serializer):
    visitor_code = serializers.CharField(max_length=6)


class VisitorCheckInSerializer(serializers.Serializer):
    visitor_code = serializers.CharField(max_length=6)
    qr_payload = serializers.CharField(max_length=64)
    direction = serializers.ChoiceField(choices=AccessLog.Direction.choices)


class MemberCheckInSerializer(serializers.Serializer):
    qr_payload = serializers.CharField(max_length=64)
    direction = serializers.ChoiceField(choices=AccessLog.Direction.choices)
    class_session_ids = serializers.ListField(
        child=serializers.UUIDField(),
        required=False,
        default=list,
    )


# ---------------------------------------------------------------------------
# Access log serializers
# ---------------------------------------------------------------------------


class AccessLogSerializer(serializers.ModelSerializer):
    person_name = serializers.SerializerMethodField()
    class_session_title = serializers.SerializerMethodField()

    class Meta:
        model = AccessLog
        fields = [
            "id",
            "person_type",
            "person_name",
            "direction",
            "method",
            "class_session",
            "class_session_title",
            "timestamp",
            "granted",
            "created_at",
        ]

    def get_person_name(self, obj):
        if obj.person_type == "visitor" and obj.visitor:
            return obj.visitor.name
        if obj.person_type == "guest" and obj.guest_name:
            return obj.guest_name
        if obj.member:
            return obj.member.user.get_full_name() or obj.member.user.email
        return "Unknown"

    def get_class_session_title(self, obj):
        if obj.class_session:
            return obj.class_session.title
        return None


# ---------------------------------------------------------------------------
# Gym Door QR serializers
# ---------------------------------------------------------------------------


class GymDoorQRSerializer(serializers.ModelSerializer):
    class Meta:
        model = GymDoorQR
        fields = [
            "id",
            "location",
            "qr_payload",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["id", "qr_payload", "created_at"]


# ---------------------------------------------------------------------------
# Equipment serializers
# ---------------------------------------------------------------------------


class EquipmentCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = EquipmentCategory
        fields = ["id", "name", "description", "created_at", "updated_at"]
        read_only_fields = ["id", "created_at", "updated_at"]


class MaintenanceLogSerializer(serializers.ModelSerializer):
    performed_by_name = serializers.SerializerMethodField()

    class Meta:
        model = MaintenanceLog
        fields = [
            "id", "equipment", "performed_by", "performed_by_name",
            "maintenance_type", "description", "cost", "date",
            "next_scheduled", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "performed_by", "created_at", "updated_at"]

    def get_performed_by_name(self, obj):
        if obj.performed_by:
            return obj.performed_by.get_full_name() or obj.performed_by.email
        return None


class EquipmentSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source="category.name", read_only=True)
    maintenance_logs = MaintenanceLogSerializer(many=True, read_only=True)

    class Meta:
        model = Equipment
        fields = [
            "id", "name", "category", "category_name", "location",
            "serial_number", "purchase_date", "purchase_price",
            "warranty_expiry", "status", "last_maintenance",
            "next_maintenance", "notes", "maintenance_logs",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


# ---------------------------------------------------------------------------
# Inventory / Supplier serializers
# ---------------------------------------------------------------------------


class SupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = [
            "id", "name", "contact_person", "email", "phone",
            "address", "notes", "is_active", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class ProductSerializer(serializers.ModelSerializer):
    is_low_stock = serializers.SerializerMethodField()

    class Meta:
        model = Product
        fields = [
            "id", "name", "sku", "description", "category",
            "price", "cost_price", "stock_quantity", "reorder_level",
            "image", "is_active", "location", "is_low_stock",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_is_low_stock(self, obj):
        return obj.stock_quantity <= obj.reorder_level


class PurchaseOrderItemSerializer(serializers.ModelSerializer):
    product_name = serializers.CharField(source="product.name", read_only=True)

    class Meta:
        model = PurchaseOrderItem
        fields = [
            "id", "order", "product", "product_name",
            "quantity", "unit_price", "received_quantity",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class PurchaseOrderSerializer(serializers.ModelSerializer):
    items = PurchaseOrderItemSerializer(many=True, read_only=True)
    supplier_name = serializers.CharField(source="supplier.name", read_only=True)

    class Meta:
        model = PurchaseOrder
        fields = [
            "id", "supplier", "supplier_name", "order_number",
            "order_date", "expected_delivery", "status",
            "total_amount", "notes", "items",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


# ---------------------------------------------------------------------------
# POS serializers
# ---------------------------------------------------------------------------


class POSTransactionItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = POSTransactionItem
        fields = [
            "id", "transaction", "product", "description",
            "quantity", "unit_price", "total_price",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class POSTransactionSerializer(serializers.ModelSerializer):
    items = POSTransactionItemSerializer(many=True, read_only=True)
    cashier_name = serializers.SerializerMethodField()

    class Meta:
        model = POSTransaction
        fields = [
            "id", "member", "cashier", "cashier_name", "location",
            "subtotal", "tax", "discount", "total",
            "payment_method", "status", "notes", "items",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "cashier", "created_at", "updated_at"]

    def get_cashier_name(self, obj):
        return obj.cashier.get_full_name() or obj.cashier.email


class GiftCardSerializer(serializers.ModelSerializer):
    class Meta:
        model = GiftCard
        fields = [
            "id", "code", "balance", "initial_balance",
            "purchased_by", "assigned_to", "is_active",
            "expires_at", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]
