from rest_framework import serializers

from .models import Refund, Order, Invoice


class RefundCreatePublicSerializer(serializers.Serializer):
	email = serializers.EmailField()
	invoice_number = serializers.CharField(required=False, allow_blank=True)
	order_id = serializers.IntegerField(required=False)

	# Optional reason fields
	reason_choice = serializers.ChoiceField(
		choices=Refund.Reason.choices, required=False
	)
	reason_text = serializers.CharField(required=False, allow_blank=True)

	def validate(self, attrs):
		email = attrs.get("email")
		invoice_number = (attrs.get("invoice_number") or "").strip()
		order_id = attrs.get("order_id")

		if not invoice_number and not order_id:
			raise serializers.ValidationError(
				"Provide either invoice_number or order_id."
			)

		order = None
		if invoice_number:
			try:
				invoice = Invoice.objects.get(invoice_number=invoice_number)
				order = invoice.order
			except Invoice.DoesNotExist:
				raise serializers.ValidationError({"invoice_number": "Invoice not found."})
			except Order.DoesNotExist:
				raise serializers.ValidationError({"invoice_number": "Order for invoice not found."})

		if order_id and order is None:
			try:
				order = Order.objects.get(id=order_id)
			except Order.DoesNotExist:
				raise serializers.ValidationError({"order_id": "Order not found."})

		# Verify email matches order's email or user's email
		if not order:
			raise serializers.ValidationError("Order could not be resolved.")

		order_email = (order.email or "").strip().lower()
		user_email = (getattr(order.user, "email", "") or "").strip().lower()
		provided = email.strip().lower()
		if provided not in {order_email, user_email}:
			raise serializers.ValidationError({"email": "Email does not match the order."})

		attrs["order"] = order
		return attrs

	def create(self, validated_data):
		order = validated_data["order"]
		reason_choice = validated_data.get("reason_choice") or Refund.Reason.OTHER
		reason_text = validated_data.get("reason_text", "")

		refund = Refund.objects.create(
			order=order,
			reason_choice=reason_choice,
			reason_text=reason_text,
		)
		return refund

from rest_framework import serializers
from drf_spectacular.utils import extend_schema_field
from decimal import Decimal
from django.contrib.auth import get_user_model

from .models import (
	Category,
	Product,
	ProductImage,
	DiscountCode,
	Refund,
	Order,
	OrderItem,
	Carrier,
	Payment,
)

User = get_user_model()


class UserBriefSerializer(serializers.ModelSerializer):
	class Meta:
		model = User
		fields = ["id", "first_name", "last_name", "email"]


class ProductBriefSerializer(serializers.ModelSerializer):
	class Meta:
		model = Product
		fields = ["id", "name", "price"]


class OrderItemReadSerializer(serializers.ModelSerializer):
	product = ProductBriefSerializer(read_only=True)
	total_price = serializers.SerializerMethodField()

	def get_total_price(self, obj):
		return obj.get_total_price(list(obj.order.discount.all()) if getattr(obj, "order", None) else None)

	class Meta:
		model = OrderItem
		fields = ["id", "product", "quantity", "total_price"]
		read_only_fields = ["id", "total_price"]


class CarrierReadSerializer(serializers.ModelSerializer):
	class Meta:
		model = Carrier
		fields = ["id", "shipping_method", "weight", "returning"]
		read_only_fields = ["id"]


class PaymentReadSerializer(serializers.Serializer):
	payment_method = serializers.CharField(read_only=True)
	stripe_id = serializers.IntegerField(source="stripe.id", read_only=True, allow_null=True)


class OrderReadSerializer(serializers.ModelSerializer):
	items = OrderItemReadSerializer(many=True, read_only=True)
	carrier = CarrierReadSerializer(read_only=True)
	payment = PaymentReadSerializer(source="payment", read_only=True)
	user = serializers.SerializerMethodField()

	def get_user(self, obj):
		request = self.context.get("request") if hasattr(self, "context") else None
		if request and getattr(request, "user", None) and request.user.is_authenticated and obj.user:
			return UserBriefSerializer(obj.user).data
		return None

	class Meta:
		model = Order
		fields = [
			"id",
			"status",
			"total_price",
			"currency",
			"first_name",
			"last_name",
			"email",
			"phone",
			"address",
			"city",
			"postal_code",
			"country",
			"note",
			"created_at",
			"updated_at",
			"carrier",
			"payment",
			"user",
			"items",
		]
		read_only_fields = [
			"id",
			"status",
			"total_price",
			"currency",
			"created_at",
			"updated_at",
		]


class OrderMiniSerializer(serializers.ModelSerializer):
	amount = serializers.DecimalField(max_digits=10, decimal_places=2, source="total_price", read_only=True)
	shipping_method = serializers.CharField(source="carrier.shipping_method", read_only=True)

	class Meta:
		model = Order
		fields = ["id", "amount", "status", "email", "shipping_method"]
		read_only_fields = fields


# ----------------- CREATE PAYLOAD SERIALIZERS (PUBLIC) -----------------

class OrderItemCreateSerializer(serializers.Serializer):
	product_id = serializers.IntegerField(label="Product ID")
	quantity = serializers.IntegerField(min_value=1, label="Quantity")


class CarrierCreateSerializer(serializers.Serializer):
	shipping_method = serializers.ChoiceField(
		choices=Carrier.SHIPPING.choices,
		label="Shipping Method",
		help_text="Choose 'store' (pickup) or 'packeta'",
	)
	weight = serializers.DecimalField(
		required=False,
		max_digits=10,
		decimal_places=2,
		label="Weight (kg)",
	)


class PaymentCreateSerializer(serializers.Serializer):
	payment_method = serializers.ChoiceField(
		choices=Payment.PAYMENT.choices,
		label="Payment Method",
		help_text="Choose 'shop', 'stripe' or 'cash_on_delivery'",
	)


class OrderCreateSerializer(serializers.Serializer):
	# Customer/billing
	first_name = serializers.CharField(max_length=100, label="First Name")
	last_name = serializers.CharField(max_length=100, label="Last Name")
	email = serializers.EmailField(label="Email")
	phone = serializers.CharField(max_length=20, required=False, allow_blank=True, label="Phone")
	address = serializers.CharField(max_length=255, label="Address")
	city = serializers.CharField(max_length=100, label="City")
	postal_code = serializers.CharField(max_length=20, label="Postal Code")
	country = serializers.CharField(max_length=100, required=False, default="Czech Republic", label="Country")
	note = serializers.CharField(required=False, allow_blank=True, label="Note")

	# Nested
	items = OrderItemCreateSerializer(many=True)
	carrier = CarrierCreateSerializer()
	payment = PaymentCreateSerializer()
	discount_codes = serializers.ListField(
		child=serializers.CharField(), required=False, allow_empty=True, label="Discount Codes"
	)

	def validate(self, attrs):
		if not attrs.get("items"):
			raise serializers.ValidationError({"items": "At least one item is required."})
		return attrs


# ----------------- ADMIN/READ MODELS -----------------

class CategorySerializer(serializers.ModelSerializer):
	class Meta:
		model = Category
		fields = [
			"id",
			"name",
			"url",
			"parent",
			"description",
			"image",
		]


class ProductImageSerializer(serializers.ModelSerializer):
	class Meta:
		model = ProductImage
		fields = [
			"id",
			"product",
			"image",
			"alt_text",
			"is_main",
		]


class ProductSerializer(serializers.ModelSerializer):
	class Meta:
		model = Product
		fields = [
			"id",
			"name",
			"description",
			"code",
			"category",
			"price",
			"url",
			"stock",
			"is_active",
			"limited_to",
			"default_carrier",
			"created_at",
			"updated_at",
		]
		read_only_fields = ["created_at", "updated_at"]


class DiscountCodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = DiscountCode
		fields = [
			"id",
			"code",
			"description",
			"percent",
			"amount",
			"valid_from",
			"valid_to",
			"active",
			"usage_limit",
			"used_count",
			"specific_products",
			"specific_categories",
		]
		read_only_fields = ["used_count"]


class RefundSerializer(serializers.ModelSerializer):
	class Meta:
		model = Refund
		fields = [
			"id",
			"order",
			"reason_choice",
			"reason_text",
			"verified",
			"created_at",
		]
		read_only_fields = ["id", "verified", "created_at"]


