package com.food.order.system.data.access.order.mapper;

import com.food.order.system.data.access.order.entity.OrderAddressEntity;
import com.food.order.system.data.access.order.entity.OrderEntity;
import com.food.order.system.data.access.order.entity.OrderItemEntity;
import com.food.order.system.domain.entity.Order;
import com.food.order.system.domain.entity.OrderItem;
import com.food.order.system.domain.entity.Product;
import com.food.order.system.domain.valueobject.OrderItemId;
import com.food.order.system.domain.valueobject.StreetAddress;
import com.food.order.system.domain.valueobject.TrackingId;
import com.food.order.sysyem.valueobject.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.food.order.system.domain.entity.Order.FAILURE_MESSAGE_DELIMITER;

@Component
public class OrderDataAccessMapper {

    public OrderEntity orderToOrderEntity(Order order){
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setId(order.getId().getValue());
        orderEntity.setOrderStatus(order.getStatus());
        orderEntity.setCustomerId(order.getCustomerId().getValue());
        orderEntity.setRestaurantId(order.getRestaurantId().getValue());
        orderEntity.setTrackingId(order.getTrackingId().getValue());
        orderEntity.setAddress(deliveryAddressToAddressEntity(order.getDeliveryAddress()));
        orderEntity.setPrice(order.getPrice().getAmount());
        orderEntity.setItems(orderItemsToOrderItemsEntity(order.getItems()));
        orderEntity.setFailureMessages(order.getFailureMessages() !=  null ?
                String.join(FAILURE_MESSAGE_DELIMITER, order.getFailureMessages()) : "");
        orderEntity.getAddress().setOrder(orderEntity);
        orderEntity.getItems().forEach(item -> item.setOrderEntity(orderEntity));
        return orderEntity;
    }

    public Order orderEntityToOrder(OrderEntity orderEntity){
        return Order.builder()
                .orderId(new OrderId(orderEntity.getId()))
                .customerId(new CustomerId(orderEntity.getCustomerId()))
                .restaurantId(new RestaurantId(orderEntity.getRestaurantId()))
                .deliveryAddress(addressEntityToDeliveryAddress(orderEntity.getAddress()))
                .price(new Money(orderEntity.getPrice()))
                .items(orderItemsEntityToOrderItems(orderEntity.getItems()))
                .trackingId(new TrackingId(orderEntity.getTrackingId()))
                .status(orderEntity.getOrderStatus())
                .failureMessages(orderEntity.getFailureMessages() != null ?
                        List.of(orderEntity.getFailureMessages().split(FAILURE_MESSAGE_DELIMITER)) :
                        new ArrayList<>())
                .build();
    }

    private List<OrderItem> orderItemsEntityToOrderItems(List<OrderItemEntity> items) {
        return items.stream()
                .map(item -> OrderItem.builder()
                        .orderItemId(new OrderItemId(item.getId()))
                        .product(new Product(new ProductId(item.getProductId())))
                        .quantity(item.getQuantity())
                        .price(new Money(item.getPrice()))
                        .subTotal(new Money(item.getSubTotal()))
                        .build())
                .toList();
    }

    private StreetAddress addressEntityToDeliveryAddress(OrderAddressEntity address) {
        return new StreetAddress(address.getId(),address.getStreet(), address.getCity() , address.getPostalCode());
    }

    private List<OrderItemEntity> orderItemsToOrderItemsEntity(List<OrderItem> items) {
        return items.stream()
                .map(item -> OrderItemEntity.builder()
                        .id(item.getId().getValue())
                        .productId(item.getProduct().getId().getValue())
                        .price(item.getPrice().getAmount())
                        .quantity(item.getQuantity())
                        .subTotal(item.getSubTotal().getAmount())
                        .build())
                .toList();
    }

    private OrderAddressEntity deliveryAddressToAddressEntity(StreetAddress deliveryAddress) {
        OrderAddressEntity orderAddressEntity = new OrderAddressEntity();
        orderAddressEntity.setId(deliveryAddress.getId());
        orderAddressEntity.setStreet(deliveryAddress.getStreet());
        orderAddressEntity.setCity(deliveryAddress.getCity());
        orderAddressEntity.setPostalCode(deliveryAddress.getPostalCode());
        return orderAddressEntity;
    }
}
