package org.hso.ecommerce.controller.intern.suppliers;

import org.hso.ecommerce.action.warehouse.SupplierOrderArrivedAction;
import org.hso.ecommerce.entities.shop.Article;
import org.hso.ecommerce.entities.supplier.SupplierOrder;
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
import org.hso.ecommerce.repos.shop.ArticleRepository;
import org.hso.ecommerce.repos.supplier.SupplierOrderRepository;
import org.hso.ecommerce.repos.warehouse.SlotRepository;
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/intern/")
public class SupplierOrderController {

	@Autowired
	private final SupplierOrderRepository supplierOrderRepository = null;

	@Autowired
	private final ArticleRepository articleRepository = null;

	@Autowired
	private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null;

	@Autowired
	private final WarehouseBookingRepository warehouseBookingRepository = null;

	@Autowired
	private final SlotRepository slotRepository = null;

	@GetMapping("supplierOrders")
	public String listSuppliers(Model model) {

		List<UImodelSupplierOrder> totals = new ArrayList<UImodelSupplierOrder>();

		for (SupplierOrder order : supplierOrderRepository.findAll()) {
			final Article article = articleRepository.findArticleByArticleOffer(order.ordered).orElse(null);
			totals.add(new UImodelSupplierOrder(order, article));
		}

		model.addAttribute("orders", totals);

		return "intern/supplierOrders/index";
	}

	@PostMapping("/supplierOrders/store/{id}")
	public String storeOrder(@PathVariable("id") Long supplierOrderID, Model model, HttpServletResponse response) {
		SupplierOrder order = supplierOrderRepository.findById(supplierOrderID).orElse(null);
		if (order == null) {
			model.addAttribute("error", "Die ausgewählte Lieferung konnte nicht gefunden werden.");
			response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
			return listSuppliers(model);
		}
		if (order.wasDelivered()) {
			model.addAttribute("error", "Die ausgewählte Lieferung wurde schon zugestellt.");
			response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
			return listSuppliers(model);
		}


		final Article article = articleRepository.findArticleByArticleOffer(order.ordered).orElse(null);
		if (article == null) {
			model.addAttribute("error", "Der bestellte Artikel wurde nicht angelegt, er hätte nicht bestellt werden dürfen.");
			response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
			return listSuppliers(model);
		}

		// Hard to do efficiently, this should be fine.
		List<WarehouseBookingPositionSlotEntry> candidates = slotRepository
				.findAll()
				.stream()
				.map(slot ->
						warehouseBookingPositionSlotEntryRepository.getBySlotNum(slot.slotNum).orElseGet(() ->
								WarehouseBookingPositionSlotEntry.empty(article, slot)
						)
				)
				.filter(entry -> entry.article.id == article.id || entry.newSumSlot == 0)
				.collect(Collectors.toList());

		SupplierOrderArrivedAction action = new SupplierOrderArrivedAction(candidates, order, article);

		try {
			SupplierOrderArrivedAction.Result result = action.finish();
			supplierOrderRepository.save(result.getOrder());
			warehouseBookingRepository.save(result.getBooking());
		} catch (SupplierOrderArrivedAction.NoSpaceInWarehouseException e) {
			e.printStackTrace();
		}

		return "redirect:/intern/warehouse/todo";
	}

	public class UImodelSupplierOrder {
		public long id;
		public String dateOrder;
		public String supplierName;
		public String articleName;
		public long articleId;
		public String priceNet;
		public String quantity;
		public String priceTotal;
		public boolean arrived;

		public UImodelSupplierOrder(SupplierOrder order, Article article) {
			this.id = order.id;
			this.supplierName = order.supplier.name;
			this.articleName = article != null ? article.title : "error";
			this.articleId = article != null ? article.id : 0;
			this.priceNet = String.format("%.2f", ((float) order.pricePerUnitNetCent / 100));
			this.quantity = String.valueOf(order.numberOfUnits);
			this.priceTotal = String.format("%.2f", ((float) order.totalPriceNet / 100));

			Date date = new Date();
			date.setTime(order.created.getTime());
			this.dateOrder = new SimpleDateFormat("dd.MM.yyyy").format(date);

			arrived = order.delivered != null;
		}
	}
}
