package com.example.orders;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 注文の受付と照会。
 */
public class OrderService {

    private Map<String, Order> orderStore = new HashMap<String, Order>();
    private ProductRepository productRepository;
    private OrderValidator validator;
    private PriceCalculator calculator;
    private int sequence = 0;

    public OrderService(ProductRepository productRepository) {
        this.productRepository = productRepository;
        this.validator = new OrderValidator(productRepository);
        this.calculator = new PriceCalculator(productRepository);
    }

    /**
     * 注文を作成する。バリデーションエラーがある場合は IllegalArgumentException。
     */
    public Order createOrder(String customerId, List<OrderLine> lines, String memberRank, String couponCode) {
        sequence = sequence + 1;
        String id = "ORD-" + String.format("%05d", sequence);
        Order order = new Order(id, customerId);
        if (lines != null) {
            Iterator<OrderLine> it = lines.iterator();
            while (it.hasNext()) {
                order.addLine(it.next());
            }
        }
        List<String> errors = validator.validate(order);
        if (errors.size() > 0) {
            throw new IllegalArgumentException("invalid order: " + errors);
        }
        int total = calculator.calcTotal(order, memberRank, couponCode);
        order.setTotalPrice(total);
        // 在庫を引き当てる
        Iterator it2 = order.getLines().iterator();
        while (it2.hasNext()) {
            OrderLine line = (OrderLine) it2.next();
            Product p = productRepository.findById(line.getProductId());
            p.setStock(p.getStock() - line.getQuantity());
        }
        orderStore.put(id, order);
        return order;
    }

    public Order findById(String orderId) {
        return orderStore.get(orderId);
    }

    /**
     * 顧客IDの前方一致で注文を検索する(大文字小文字は区別しない)。
     */
    public List<Order> findByCustomerPrefix(String prefix) {
        List<Order> result = new ArrayList<Order>();
        if (prefix == null || prefix.trim().length() == 0) {
            return result;
        }
        String p = prefix.toLowerCase();
        Iterator<Order> it = orderStore.values().iterator();
        while (it.hasNext()) {
            Order o = it.next();
            if (o.getCustomerId().toLowerCase().startsWith(p)) {
                result.add(o);
            }
        }
        return result;
    }

    /**
     * キャンセル。SHIPPED 以降はキャンセル不可。
     */
    public boolean cancel(String orderId) {
        Order order = orderStore.get(orderId);
        if (order == null) {
            return false;
        }
        if (order.getStatus().equals("SHIPPED")) {
            return false;
        }
        order.setStatus("CANCELED");
        // 在庫を戻す
        Iterator it = order.getLines().iterator();
        while (it.hasNext()) {
            OrderLine line = (OrderLine) it.next();
            Product p = productRepository.findById(line.getProductId());
            p.setStock(p.getStock() + line.getQuantity());
        }
        return true;
    }
}
