from decimal import Decimal, ROUND_HALF_UP
from apps.business.schemes.models import OpportunityBundleDistribution


def resolve_distribution_base_amount(product, fallback_amount):
	"""
	Resolve base amount for distribution computation.

	If product has a opportunity_bundle with configured opportunity_bundle_amount (>0), use that.
	Otherwise, fallback to the provided amount (typically purchase amount/base cost).
	"""
	opportunity_bundle = getattr(product, 'opportunity_bundle', None)
	if opportunity_bundle is not None:
		opportunity_bundle_amount = Decimal(str(getattr(opportunity_bundle, 'opportunity_bundle_amount', 0) or 0))
		if opportunity_bundle_amount > 0:
			return opportunity_bundle_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)

	return Decimal(str(fallback_amount or 0)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)

def calculate_distribution(product, base_amount):
	"""
	Calculate distribution breakdown for a product using base_amount.
	Args:
		product: Product instance
		base_amount: Decimal
	Returns:
		dict: {"total": base_amount, "breakdown": [{"type": ..., "value_type": ..., "amount": ...}]}
	"""
	opportunity_bundle = getattr(product, 'opportunity_bundle', None)
	if not opportunity_bundle:
		raise Exception("No opportunity_bundle attached to product.")

	distributions = OpportunityBundleDistribution.objects.filter(opportunity_bundle=opportunity_bundle).order_by('component_type')
	if not distributions.exists():
		raise Exception("No distribution config found for opportunity_bundle.")

	breakdown = []
	total = Decimal('0.00')
	valid_types = set(choice[0] for choice in OpportunityBundleDistribution.ComponentType.choices)
	for dist in distributions:
		if dist.component_type not in valid_types:
			raise Exception(f"Unknown component_type: {dist.component_type}")
		if dist.value_type == OpportunityBundleDistribution.ValueType.FIXED:
			amount = dist.value
		elif dist.value_type == OpportunityBundleDistribution.ValueType.PERCENT:
			amount = (base_amount * dist.value / Decimal('100.00'))
		else:
			raise Exception(f"Unknown value_type: {dist.value_type}")
		amount = amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
		breakdown.append({
			"type": dist.component_type,
			"value_type": dist.value_type,
			"amount": amount
		})
		total += amount

	total = total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
	if total != base_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP):
		raise Exception(f"Distribution total ({total}) does not match base_amount ({base_amount}).")

	return {"total": base_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP), "breakdown": breakdown}
