package mappers

import (
	"testing"
	"time"

	"apskel-pos-be/internal/entities"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
)

func TestOrderItemEntityToResponse_WithProductNames(t *testing.T) {
	// Arrange
	productID := uuid.New()
	variantID := uuid.New()
	orderID := uuid.New()
	itemID := uuid.New()

	product := entities.Product{
		ID:   productID,
		Name: "Test Product",
	}

	productVariant := entities.ProductVariant{
		ID:   variantID,
		Name: "Test Variant",
	}

	orderItem := &entities.OrderItem{
		ID:               itemID,
		OrderID:          orderID,
		ProductID:        productID,
		ProductVariantID: &variantID,
		Quantity:         2,
		UnitPrice:        10.0,
		TotalPrice:       20.0,
		UnitCost:         5.0,
		TotalCost:        10.0,
		Status:           entities.OrderItemStatusPending,
		CreatedAt:        time.Now(),
		UpdatedAt:        time.Now(),
		Product:          product,
		ProductVariant:   &productVariant,
	}

	// Act
	result := OrderItemEntityToResponse(orderItem)

	// Assert
	assert.NotNil(t, result)
	assert.Equal(t, itemID, result.ID)
	assert.Equal(t, orderID, result.OrderID)
	assert.Equal(t, productID, result.ProductID)
	assert.Equal(t, "Test Product", result.ProductName)
	assert.Equal(t, &variantID, result.ProductVariantID)
	assert.Equal(t, "Test Variant", *result.ProductVariantName)
	assert.Equal(t, 2, result.Quantity)
	assert.Equal(t, 10.0, result.UnitPrice)
	assert.Equal(t, 20.0, result.TotalPrice)
}

func TestOrderItemEntityToResponse_WithoutProductVariant(t *testing.T) {
	// Arrange
	productID := uuid.New()
	orderID := uuid.New()
	itemID := uuid.New()

	product := entities.Product{
		ID:   productID,
		Name: "Test Product",
	}

	orderItem := &entities.OrderItem{
		ID:               itemID,
		OrderID:          orderID,
		ProductID:        productID,
		ProductVariantID: nil,
		Quantity:         1,
		UnitPrice:        15.0,
		TotalPrice:       15.0,
		UnitCost:         7.0,
		TotalCost:        7.0,
		Status:           entities.OrderItemStatusPending,
		CreatedAt:        time.Now(),
		UpdatedAt:        time.Now(),
		Product:          product,
		ProductVariant:   nil,
	}

	// Act
	result := OrderItemEntityToResponse(orderItem)

	// Assert
	assert.NotNil(t, result)
	assert.Equal(t, itemID, result.ID)
	assert.Equal(t, orderID, result.OrderID)
	assert.Equal(t, productID, result.ProductID)
	assert.Equal(t, "Test Product", result.ProductName)
	assert.Nil(t, result.ProductVariantID)
	assert.Nil(t, result.ProductVariantName)
	assert.Equal(t, 1, result.Quantity)
	assert.Equal(t, 15.0, result.UnitPrice)
	assert.Equal(t, 15.0, result.TotalPrice)
}

func TestOrderItemEntityToResponse_WithoutProductPreload(t *testing.T) {
	// Arrange
	productID := uuid.New()
	orderID := uuid.New()
	itemID := uuid.New()

	// Create order item without preloaded product (empty product)
	orderItem := &entities.OrderItem{
		ID:               itemID,
		OrderID:          orderID,
		ProductID:        productID,
		ProductVariantID: nil,
		Quantity:         1,
		UnitPrice:        10.0,
		TotalPrice:       10.0,
		UnitCost:         5.0,
		TotalCost:        5.0,
		Status:           entities.OrderItemStatusPending,
		CreatedAt:        time.Now(),
		UpdatedAt:        time.Now(),
		Product:          entities.Product{}, // Empty product
		ProductVariant:   nil,
	}

	// Act
	result := OrderItemEntityToResponse(orderItem)

	// Assert
	assert.NotNil(t, result)
	assert.Equal(t, itemID, result.ID)
	assert.Equal(t, orderID, result.OrderID)
	assert.Equal(t, productID, result.ProductID)
	assert.Equal(t, "", result.ProductName) // Should be empty since product is not preloaded
	assert.Nil(t, result.ProductVariantID)
	assert.Nil(t, result.ProductVariantName)
}
