package com.example.kafka.service;

import com.example.kafka.entity.Order;
import com.example.kafka.enumerator.OrderStatus;
import com.example.kafka.producer.MessageProducer;
import com.example.kafka.repository.OrderRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

/**
 * OrderServiceImpl is implementation of OrderService class
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class.getName());

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private MessageProducer messageProducer;

    /**
     * Save order data into DB
     * @param order The order
     * @return The mono of order
     */
    @Override
    public Mono<Order> saveOrderIntoDB(Order order){
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            messageProducer.publishOrder(objectMapper.writeValueAsString(order));
        } catch(JsonProcessingException e) {
            log.error("Caught Exception {}:: ",e);
        }
        return orderRepository.save(order);
    }


    /**
     * Validate the order to either accept or reject
     * @param orderJson The order json
     */
    @Override
    public void validateOrder(String orderJson) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Order order = mapper.readValue(orderJson,Order.class);
            userService.findById(order.getId()).flatMap(user -> {
                order.setOrderStatus(order.getAmount()<=user.getBalance() ? OrderStatus.ACCEPTED : OrderStatus.REJECTED);
                return orderRepository.save(order);
            }).subscribe();
        } catch(JsonProcessingException e) {
            log.error("Caught Exception :: {} ",e);
        }
    }
}
