package cart

import (
	"fmt"

	messages "git.tornberg.me/go-cart-actor/pkg/messages"
)

// mutation_add_item.go
//
// Registers the AddItem cart mutation in the generic mutation registry.
// This replaces the legacy switch-based logic previously found in CartGrain.Apply.
//
// Behavior:
//   * Validates quantity > 0
//   * If an item with same SKU exists -> increases quantity
//   * Else creates a new CartItem with computed tax amounts
//   * Totals recalculated automatically via WithTotals()
//
// NOTE: Any future field additions in messages.AddItem that affect pricing / tax
// must keep this handler in sync.

func AddItem(g *CartGrain, m *messages.AddItem) error {
	if m == nil {
		return fmt.Errorf("AddItem: nil payload")
	}
	if m.Quantity < 1 {
		return fmt.Errorf("AddItem: invalid quantity %d", m.Quantity)
	}

	// Merge with any existing item having same SKU and matching StoreId (including both nil).
	for _, existing := range g.Items {
		if existing.Sku != m.Sku {
			continue
		}
		sameStore := (existing.StoreId == nil && m.StoreId == nil) ||
			(existing.StoreId != nil && m.StoreId != nil && *existing.StoreId == *m.StoreId)
		if !sameStore {
			continue
		}
		existing.Quantity += int(m.Quantity)
		existing.Stock = StockStatus(m.Stock)
		// If existing had nil store but new has one, adopt it.
		if existing.StoreId == nil && m.StoreId != nil {
			existing.StoreId = m.StoreId
		}
		return nil
	}

	g.mu.Lock()
	defer g.mu.Unlock()

	g.lastItemId++
	taxRate := float32(25.0)
	if m.Tax > 0 {
		taxRate = float32(int(m.Tax) / 100)
	}

	pricePerItem := NewPriceFromIncVat(m.Price, taxRate)

	g.Items = append(g.Items, &CartItem{
		Id:       g.lastItemId,
		ItemId:   uint32(m.ItemId),
		Quantity: int(m.Quantity),
		Sku:      m.Sku,
		Meta: &ItemMeta{
			Name:       m.Name,
			Image:      m.Image,
			Brand:      m.Brand,
			Category:   m.Category,
			Category2:  m.Category2,
			Category3:  m.Category3,
			Category4:  m.Category4,
			Category5:  m.Category5,
			Outlet:     m.Outlet,
			SellerId:   m.SellerId,
			SellerName: m.SellerName,
		},
		SaleStatus: m.SaleStatus,
		ParentId:   m.ParentId,

		Price:      *pricePerItem,
		TotalPrice: *MultiplyPrice(*pricePerItem, int64(m.Quantity)),

		Stock:      StockStatus(m.Stock),
		Disclaimer: m.Disclaimer,

		OrgPrice:    getOrgPrice(m.OrgPrice, taxRate),
		ArticleType: m.ArticleType,

		StoreId: m.StoreId,
	})
	g.UpdateTotals()
	return nil
}

func getOrgPrice(orgPrice int64, taxRate float32) *Price {
	if orgPrice <= 0 {
		return nil
	}
	return NewPriceFromIncVat(orgPrice, taxRate)
}
