from rest_framework import serializers
from .models import (
    Asset, AssetCategory, AssetLocation, AssetAssignment, AssetTicket, AssetDocument,
    Maintenance, Procurement, Vendor, License, Rental, StockItem, StockLevel, StockMovement,
)


class AssetSerializer(serializers.ModelSerializer):
    """Serializer for Asset model."""
    category_name = serializers.SerializerMethodField()
    location_name = serializers.SerializerMethodField()
    assigned_to_name = serializers.SerializerMethodField()
    vendor_name = serializers.SerializerMethodField()
    purchase_order_number = serializers.SerializerMethodField()
    goods_receipt_number = serializers.SerializerMethodField()

    class Meta:
        model = Asset
        fields = [
            "id", "name", "asset_tag", "category", "category_name", "serial_number",
            "status", "location", "location_name",
            "vendor", "vendor_name",
            "purchase_order", "purchase_order_number",
            "goods_receipt", "goods_receipt_number",
            "purchase_date", "purchase_price",
            "warranty_expiry", "description", "image", "specifications", "assigned_to_name",
            "created_at", "updated_at"
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_category_name(self, obj):
        if obj.category:
            return obj.category.name
        return None

    def get_location_name(self, obj):
        if obj.location:
            return obj.location.name
        return None

    def get_assigned_to_name(self, obj):
        # Prefetch already filters status='assigned'; just take first cached row.
        cached = obj.assignments.all()
        if cached:
            return str(cached[0].employee)
        return None

    def get_vendor_name(self, obj):
        return obj.vendor.name if obj.vendor_id else None

    def get_purchase_order_number(self, obj):
        return obj.purchase_order.order_number if obj.purchase_order_id else None

    def get_goods_receipt_number(self, obj):
        return obj.goods_receipt.receipt_number if obj.goods_receipt_id else None


class AssetCategorySerializer(serializers.ModelSerializer):
    """Serializer for AssetCategory model."""

    class Meta:
        model = AssetCategory
        fields = ["id", "slug", "name", "description", "depreciation_rate"]
        read_only_fields = ["id"]


class AssetLocationSerializer(serializers.ModelSerializer):
    """Serializer for AssetLocation model."""

    class Meta:
        model = AssetLocation
        fields = ["id", "slug", "name", "address", "contact_person", "contact_phone"]
        read_only_fields = ["id"]


class AssetAssignmentSerializer(serializers.ModelSerializer):
    """Serializer for AssetAssignment model."""
    asset_name = serializers.SerializerMethodField()
    asset_tag = serializers.SerializerMethodField()
    serial_number = serializers.CharField(source="asset.serial_number", read_only=True)
    category_name = serializers.SerializerMethodField()
    employee_name = serializers.SerializerMethodField()

    class Meta:
        model = AssetAssignment
        fields = ["id", "asset", "asset_name", "asset_tag", "serial_number", "category_name", "employee", "employee_name", "assigned_date", "returned_date", "status", "condition", "notes"]
        read_only_fields = ["id"]

    def get_asset_name(self, obj):
        return obj.asset.name

    def get_asset_tag(self, obj):
        return obj.asset.asset_tag

    def get_category_name(self, obj):
        if obj.asset.category:
            return obj.asset.category.name
        return None

    def get_employee_name(self, obj):
        return str(obj.employee)


class MaintenanceSerializer(serializers.ModelSerializer):
    """Serializer for Maintenance model."""
    asset_name = serializers.SerializerMethodField()

    class Meta:
        model = Maintenance
        fields = [
            "id", "asset", "asset_name", "title", "description", "status",
            "scheduled_date", "completed_date", "cost", "vendor", "notes", "created_at"
        ]
        read_only_fields = ["id", "created_at"]

    def get_asset_name(self, obj):
        return f"{obj.asset.asset_tag} - {obj.asset.name}"


class ProcurementSerializer(serializers.ModelSerializer):
    """Serializer for Procurement model."""
    requested_by_name = serializers.SerializerMethodField()
    vendor_name = serializers.SerializerMethodField()
    total_amount = serializers.DecimalField(
        source="estimated_cost", max_digits=12, decimal_places=2,
        required=False, allow_null=True,
    )
    order_date = serializers.SerializerMethodField()

    class Meta:
        model = Procurement
        fields = [
            "id", "number", "title", "description", "status", "requested_by", "requested_by_name",
            "category", "quantity", "estimated_cost", "actual_cost", "total_amount",
            "vendor", "vendor_name", "items", "order_date", "delivery_date", "notes",
            "requisition", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "number", "requested_by", "requisition", "created_at", "updated_at"]

    def get_requested_by_name(self, obj):
        return obj.requested_by.get_full_name() or obj.requested_by.username

    def get_vendor_name(self, obj):
        if obj.vendor:
            return obj.vendor.name
        return None

    def get_order_date(self, obj):
        return obj.created_at.date().isoformat() if obj.created_at else None


class AssetTicketSerializer(serializers.ModelSerializer):
    """Serializer for AssetTicket model."""
    asset_name = serializers.SerializerMethodField()
    asset_tag = serializers.SerializerMethodField()
    reported_by_name = serializers.SerializerMethodField()
    assigned_to_name = serializers.SerializerMethodField()

    class Meta:
        model = AssetTicket
        fields = [
            "id", "title", "description", "priority", "status",
            "asset", "asset_name", "asset_tag",
            "reported_by", "reported_by_name",
            "assigned_to", "assigned_to_name",
            "resolved_at", "notes", "created_at", "updated_at"
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_asset_name(self, obj):
        return obj.asset.name if obj.asset else None

    def get_asset_tag(self, obj):
        return obj.asset.asset_tag if obj.asset else None

    def get_reported_by_name(self, obj):
        if obj.reported_by:
            return obj.reported_by.get_full_name() or obj.reported_by.username
        return None

    def get_assigned_to_name(self, obj):
        if obj.assigned_to:
            return obj.assigned_to.get_full_name() or obj.assigned_to.username
        return None


class VendorSerializer(serializers.ModelSerializer):
    """Serializer for Vendor model."""

    class Meta:
        model = Vendor
        fields = ["id", "name", "contact_person", "email", "phone", "address", "tax_id", "bank_details", "notes", "created_at"]
        read_only_fields = ["id", "created_at"]

class AssetDocumentSerializer(serializers.ModelSerializer):
    """Serializer for AssetDocument model."""
    file_url = serializers.SerializerMethodField()
    uploaded_by_name = serializers.SerializerMethodField()

    class Meta:
        model = AssetDocument
        fields = [
            "id", "asset", "title", "doc_type", "file", "file_url",
            "notes", "uploaded_by", "uploaded_by_name", "created_at",
        ]
        read_only_fields = ["id", "uploaded_by", "created_at"]

    def get_file_url(self, obj):
        if not obj.file:
            return None
        request = self.context.get("request")
        url = obj.file.url
        return request.build_absolute_uri(url) if request else url

    def get_uploaded_by_name(self, obj):
        if obj.uploaded_by:
            return obj.uploaded_by.get_full_name() or obj.uploaded_by.username
        return None


class LicenseSerializer(serializers.ModelSerializer):
    """Serializer for License / subscription records."""
    vendor_name = serializers.SerializerMethodField()

    class Meta:
        model = License
        fields = [
            "id", "name", "vendor", "vendor_name", "license_key", "seats",
            "cost_per_period", "period", "start_date", "renewal_date", "auto_renew",
            "status", "purchase_order", "goods_receipt", "notes", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_vendor_name(self, obj):
        return obj.vendor.name if obj.vendor_id else None


class RentalSerializer(serializers.ModelSerializer):
    """Serializer for Rental records."""
    vendor_name = serializers.SerializerMethodField()
    location_name = serializers.SerializerMethodField()

    class Meta:
        model = Rental
        fields = [
            "id", "name", "vendor", "vendor_name", "quantity", "location", "location_name",
            "rental_cost", "deposit", "start_date", "return_date", "returned_at",
            "returned_condition", "status", "purchase_order", "goods_receipt",
            "notes", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_vendor_name(self, obj):
        return obj.vendor.name if obj.vendor_id else None

    def get_location_name(self, obj):
        return obj.location.name if obj.location_id else None


class StockItemSerializer(serializers.ModelSerializer):
    """Serializer for StockItem catalog records, with rolled-up on-hand qty."""
    category_name = serializers.SerializerMethodField()
    vendor_name = serializers.SerializerMethodField()
    total_quantity = serializers.IntegerField(read_only=True)
    is_low = serializers.SerializerMethodField()

    class Meta:
        model = StockItem
        fields = [
            "id", "name", "sku", "category", "category_name", "unit", "reorder_point",
            "unit_cost", "vendor", "vendor_name", "total_quantity", "is_low",
            "notes", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_category_name(self, obj):
        return obj.category.name if obj.category_id else None

    def get_vendor_name(self, obj):
        return obj.vendor.name if obj.vendor_id else None

    def get_is_low(self, obj):
        return obj.total_quantity <= obj.reorder_point


class StockLevelSerializer(serializers.ModelSerializer):
    """Serializer for per-location StockLevel rows."""
    item_name = serializers.SerializerMethodField()
    location_name = serializers.SerializerMethodField()

    class Meta:
        model = StockLevel
        fields = ["id", "item", "item_name", "location", "location_name", "quantity", "updated_at"]
        read_only_fields = ["id", "quantity", "updated_at"]

    def get_item_name(self, obj):
        return obj.item.name if obj.item_id else None

    def get_location_name(self, obj):
        return obj.location.name if obj.location_id else None


class StockMovementSerializer(serializers.ModelSerializer):
    """Serializer for StockMovement ledger entries. Applying happens in the ViewSet."""
    item_name = serializers.SerializerMethodField()
    location_name = serializers.SerializerMethodField()
    performed_by_name = serializers.SerializerMethodField()

    class Meta:
        model = StockMovement
        fields = [
            "id", "item", "item_name", "location", "location_name", "movement_type",
            "quantity", "reason", "goods_receipt", "performed_by", "performed_by_name", "created_at",
        ]
        read_only_fields = ["id", "performed_by", "created_at"]

    def get_item_name(self, obj):
        return obj.item.name if obj.item_id else None

    def get_location_name(self, obj):
        return obj.location.name if obj.location_id else None

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