package com.zfire.mall.manager.logic.stock;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.admin.respDto.AdminUserDto;
import com.zfire.mall.manager.bean.stock.AdminUserForceStockExcel;
import com.zfire.mall.manager.bean.stock.StockCategory;
import com.zfire.mall.manager.bean.stock.StockForceAdd;
import com.zfire.mall.manager.bean.stock.StockForceUserAdd;
import com.zfire.mall.manager.commonmapper.CommonMapper;
import com.zfire.mall.manager.constant.Constant;
import com.zfire.mall.manager.enums.OrderFullStatusEnum;
import com.zfire.mall.manager.enums.OrderTypeEnum;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.*;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j;
import org.ehcache.core.util.CollectionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Log4j
public class StockForceLogic{

    @Autowired
    StockForceCategoryService stockForceCategoryService;

    @Autowired
    StockForceService stockForceService;

    @Autowired
    StockCorrespondService stockCorrespondService;

    @Autowired
    KingDeeCategoryService kingDeeCategoryService;

    @Autowired
    AdminUserForceStockService adminUserForceStockService;

    @Autowired
    CommonMapper commonMapper;

    @Autowired
    AdminUserService adminUserService;

    @Autowired
    RetailOrderService retailOrderService;

    @Autowired
    RetailOrderItemService retailOrderItemService;

    @Autowired
    EnginOrderService enginOrderService;

    @Autowired
    EnginOrderItemService enginOrderItemService;


    @Transactional(rollbackFor = Exception.class)
    public void update(StockForceAdd stockForceAdd) {
        List<String> collect = stockForceService.lambdaQuery().list().stream().map(StockForce::getId).collect(Collectors.toList());
        List<String> collects = stockForceCategoryService.lambdaQuery().list().stream().map(StockForceCategory::getId).collect(Collectors.toList());
        stockForceService.removeByIds(collect);
        stockForceCategoryService.removeByIds(collects);


        stockForceAdd.insert();
        stockForceCategoryService.saveBatch(stockForceAdd.getStockForceCategories());
    }

    public StockForceAdd deatil() {
        StockForce stock = stockForceService.lambdaQuery().last("limit 1").one();

        if (stock == null)
            return null;

        List<StockForceCategory> list = stockForceCategoryService.lambdaQuery().list();

        StockForceAdd stockForceAdd = BeanUtil.toBean(stock, StockForceAdd.class);

        stockForceAdd.setStockForceCategories(list);
        return stockForceAdd;

    }

    @Transactional(rollbackFor = Exception.class)
    public void del() {
        List<String> collect = stockForceService.lambdaQuery().list().stream().map(StockForce::getId).collect(Collectors.toList());
        List<String> collects = stockForceCategoryService.lambdaQuery().list().stream().map(StockForceCategory::getId).collect(Collectors.toList());
        stockForceService.removeByIds(collect);
        stockForceCategoryService.removeByIds(collects);
    }

    public List<StockCategory> list() {
        List<StockCorrespond> list = stockCorrespondService.lambdaQuery().eq(StockCorrespond::getType,1).list();
        List<KingDeeCategory> categories = kingDeeCategoryService.lambdaQuery().list();
        List<StockCategory> stockCategories = BeanUtil.copyToList(list, StockCategory.class);
        stockCategories.stream().forEach(item -> {
            item.setKingDeeCategories(categories);
        });
        return stockCategories;
    }

    @Transactional(rollbackFor = Exception.class)
    public void addForceUser(StockForceUserAdd stockForceUserAdd) {
        adminUserForceStockService.lambdaUpdate()
                .eq(AdminUserForceStock::getAdminUserId,stockForceUserAdd.getAdminUserId()).remove();
        if (!CollectionUtils.isEmpty(stockForceUserAdd.getAdminUserForceStocks())) {

            List<KingDeeCategory> kingDeeCategories = kingDeeCategoryService.lambdaQuery().list();

            for (AdminUserForceStock adminUserForceStock : stockForceUserAdd.getAdminUserForceStocks()) {
                KingDeeCategory kingDeeCategory = kingDeeCategories.stream().filter(item -> item.getId().equals(adminUserForceStock.getCategoryId())).collect(Collectors.toList()).get(0);
                adminUserForceStock.setCategoryName(kingDeeCategory.getName());
            }
            adminUserForceStockService.saveBatch(stockForceUserAdd.getAdminUserForceStocks());
        }
    }


    public List<AdminUserForceStock> forceStockList(String adminUserId) {
        return adminUserForceStockService.lambdaQuery()
                .eq(AdminUserForceStock::getAdminUserId, adminUserId).list();
    }

    public IPage<AdminUserForceStockExcel> listExcel(int i, int i1) {

        IPage<AdminUserForceStockExcel> adminUserIPage = commonMapper.listExcel(new Page(i, i1));
        List<AdminUserForceStock> list = adminUserForceStockService.lambdaQuery().list();
        for (AdminUserForceStockExcel record : adminUserIPage.getRecords()) {
            List<String> collect = list.stream().filter(item -> item.getAdminUserId().equals(record.getAdminUserId())
                    && item.getCorrespondName().equals(record.getStockName())).map(AdminUserForceStock::getCategoryName).collect(Collectors.toList());
            String join = String.join(",", collect);
            record.setStockCategory(join);
        }
        return adminUserIPage;
    }

    public ExcelData listExcelEx(List<AdminUserForceStockExcel> records) {
        String[] titles = new String[]{"账号", "账号名称","仓库名称","仓库强制分类"};
        List<List<Object>> rows = new ArrayList<>();
        for (AdminUserForceStockExcel adminUserForceStockExcel : records) {
            List<Object> row = new ArrayList<>();
            row.add(adminUserForceStockExcel.getUserName());
            row.add(adminUserForceStockExcel.getNickName());
            row.add(adminUserForceStockExcel.getStockName());
            row.add(adminUserForceStockExcel.getStockCategory());
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        excelData.setName("sheet1");
        return excelData;
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchUpdate(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        reader.addHeaderAlias("账号编号", "adminUserId");
        reader.addHeaderAlias("仓库", "correspondName");
        reader.addHeaderAlias("是否全选品类", "id");
        reader.addHeaderAlias("强制品类（非全选需填，多个逗号隔开）", "categoryName");

        List<AdminUserForceStock> adminUserForceStocks = reader.readAll(AdminUserForceStock.class);
        List<KingDeeCategory> list = kingDeeCategoryService.lambdaQuery().list();

        List<AdminUserForceStock> adminUserForceStocksList = new ArrayList<>();
        List<String> adminUserId = new ArrayList<>();
        for (AdminUserForceStock adminUserForceStock : adminUserForceStocks) {
            AdminUser adminUser = adminUserService.lambdaQuery()
                    .eq(AdminUser::getUserName, adminUserForceStock.getAdminUserId())
                    .last("limit 1").one();
            StockCorrespond stockCorrespond = stockCorrespondService.lambdaQuery()
                    .eq(StockCorrespond::getName, adminUserForceStock.getCorrespondName())
                    .last("limit 1").one();

            adminUserId.add(adminUser.getAdminUserId());

            if (adminUserForceStock.getId().equals("是")){
                for (KingDeeCategory kingDeeCategory : list) {
                    AdminUserForceStock adminUserForceStock1 = new AdminUserForceStock();
                    adminUserForceStock1.setCorrespondId(stockCorrespond.getId());
                    adminUserForceStock1.setCorrespondName(stockCorrespond.getName());
                    adminUserForceStock1.setAdminUserId(adminUser.getAdminUserId());
                    adminUserForceStock1.setCategoryId(kingDeeCategory.getId());
                    adminUserForceStock1.setCategoryName(kingDeeCategory.getName());
                    adminUserForceStocksList.add(adminUserForceStock1);
                }
            }else {
                String[] split = adminUserForceStock.getCategoryName().split(",|，");
                for (String s : split) {

                    KingDeeCategory kingDeeCategory = list.stream().filter(item -> item.getName().equals(s)).collect(Collectors.toList()).get(0);

                    AdminUserForceStock adminUserForceStock1 = new AdminUserForceStock();
                    adminUserForceStock1.setCorrespondId(stockCorrespond.getId());
                    adminUserForceStock1.setCorrespondName(stockCorrespond.getName());
                    adminUserForceStock1.setAdminUserId(adminUser.getAdminUserId());
                    adminUserForceStock1.setCategoryId(kingDeeCategory.getId());
                    adminUserForceStock1.setCategoryName(kingDeeCategory.getName());
                    adminUserForceStocksList.add(adminUserForceStock1);
                }


            }

        }

        adminUserForceStockService.lambdaUpdate().in(AdminUserForceStock::getAdminUserId,adminUserId).remove();
        adminUserForceStockService.saveBatch(adminUserForceStocksList);
    }


    @SneakyThrows
    @Async("asyncExecutor")
    public void syncStockThreeSync(RetailOrderItem retailOrderItem, List<StockXz> stockXzList, List<SalesOrder> salesOrderList,
                                   List<SalesOrderItem> salesOrderItemList, Map<String, List<String>> stockMap) {

        for (int i = 0; i < 130; i++) {
            String dateStr = "2024-03-21 00:00:00";

            DateTime dateTime = DateUtil.parse(dateStr);

            DateTime parse = DateUtil.offsetDay(dateTime, i);

            if (parse.after(DateUtil.offsetDay(new DateTime(), -1)))
                break;


            RetailOrder retailOrder = retailOrderService.getById(retailOrderItem.getRetailOrderId());

            RetailOrderItem retailOrderItemServiceById = retailOrderItemService.getById(retailOrderItem.getId());

            if (parse.before(retailOrder.getExamineTime()))
                continue;


            //审批之后
            List<String> salesIds = salesOrderList.stream()
                    .filter(item -> item.getApprovalTime() != null && item.getApprovalTime().after(parse))
                    .map(SalesOrder::getId).collect(Collectors.toList());

            //没有审批
            salesIds.addAll(salesOrderList.stream()
                    .filter(item -> item.getApprovalTime() == null)
                    .map(SalesOrder::getId).collect(Collectors.toList()));

            Integer integer = salesOrderItemList.stream().filter(item -> item.getMaterialId().equals(retailOrderItem.getMaterialId())
                    && salesIds.contains(item.getSalesOrderNo()) && item.getOrderId().equals(retailOrderItem.getId())
            ).map(SalesOrderItem::getRefundableQty).reduce(Integer::sum).orElse(0);

            Integer refundQty = retailOrderItem.getRefundableQty() + integer;



            List<String> strings = stockMap.get(retailOrder.getCustomerId());


            Integer stockQty = stockXzList.stream().filter(item -> strings.contains(item.getStockName()) &&
                    item.getMId().equals(retailOrderItem.getMaterialId()) && item.getXzTime().after(DateUtil.beginOfDay(parse))
                    && item.getXzTime().before(DateUtil.endOfDay(parse))
            ).map(StockXz::getQty).reduce(Integer::sum).orElse(0);

            if (stockQty < 1)
                continue;

            if (refundQty < 1)
                break;


            Integer betweenDay = retailOrderItemServiceById.getFullNum() == null ? 1 : retailOrderItemServiceById.getFullNum() + 1;


            if (stockQty < refundQty)
                refundQty = stockQty;


            String costId = "";

            if (betweenDay > 5) {
                OrderFullCost orderFullCost = new OrderFullCost();
                orderFullCost.setYearTime(Convert.toStr(parse.year()));
                orderFullCost.setMonthTime(Convert.toStr(parse.month() + 1));
                orderFullCost.setStatus(OrderFullStatusEnum.ENABLE.getKey());
                orderFullCost.setOrderType(retailOrder.getType().equals(1) ? OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey());
                orderFullCost.setOrderNo(retailOrder.getId());
                orderFullCost.setOrderTime(retailOrder.getTheTime());
                orderFullCost.setExamineTime(retailOrder.getExamineTime());
                orderFullCost.setCustomerId(retailOrder.getCustomerId());
                orderFullCost.setCustomerName(retailOrder.getCustomerName());
                orderFullCost.setCustomerNumber(retailOrder.getCustomerNumber());
                orderFullCost.setMaterialId(retailOrderItem.getMaterialId());
                orderFullCost.setMaterialCode(retailOrderItem.getMaterialCode());
                orderFullCost.setMaterialName(retailOrderItem.getMaterialName());
                orderFullCost.setMaterialOldNumber(retailOrderItem.getMaterialOldNumber());
                orderFullCost.setSpecification(retailOrderItem.getSpecification());
                orderFullCost.setOrderNum(refundQty);

                BigDecimal price = new BigDecimal(0);

                if (refundQty.equals(retailOrderItem.getQty())) {
                    price = retailOrderItem.getTotalAmount();
                } else {
                    price = retailOrderItem.getTotalAmount()
                            .divide(Convert.toBigDecimal(retailOrderItem.getQty())).multiply(Convert.toBigDecimal(refundQty));
                }

                orderFullCost.setPayAmount(price);

                orderFullCost.setOverdueNum(Convert.toInt(betweenDay - 5));

                orderFullCost.setFullCost(orderFullCost.getOverdueNum() < 15 ? price.multiply(Constant.STORAGE_FEE_ONE).setScale(2, BigDecimal.ROUND_HALF_UP)
                        : price.multiply(Constant.STORAGE_FEE_TWO).setScale(2, BigDecimal.ROUND_HALF_UP));

                orderFullCost.setCustomerWalletId(retailOrderItem.getCustomerWalletId());
                orderFullCost.setCustomerWalletName(retailOrderItem.getCustomerWalletName());
                orderFullCost.setCustomerWalletNumber(retailOrderItem.getCustomerWalletNumber());
                orderFullCost.setK3CategoryId(retailOrderItem.getK3CategoryId());
                orderFullCost.setK3CategoryName(retailOrderItem.getK3CategoryName());
                orderFullCost.setK3CategoryNumber(retailOrderItem.getK3CategoryNumber());
                orderFullCost.setFullStartTime(retailOrderItem.getFullTime());

                orderFullCost.setFullEndTime(DateUtil.beginOfDay(parse));

                orderFullCost.setFullNum(Convert.toInt(betweenDay));


                orderFullCost.setNote("自货满日五天内免费，逾期15天内收取订单机型金额万分之3，逾15天以上收取订单机型金额万分之四，该单机型货满已" + betweenDay + "天，收取逾期第" + orderFullCost.getOverdueNum() + "天订单机型金额*" +
                        (orderFullCost.getOverdueNum() < 15 ? "万分之3" : "万分之4") + "（" + price + "*" + (orderFullCost.getOverdueNum() < 15 ? "万分之3" : "万分之4") + " = " + orderFullCost.getFullCost() + "）");

                orderFullCost.insert();

                costId = orderFullCost.getOrderFullCostId();
            }

            OrderFullDate orderFullDate = new OrderFullDate();
            orderFullDate.setYearTime(Convert.toStr(parse.year()));
            orderFullDate.setMonthTime(Convert.toStr(parse.month() + 1));
            orderFullDate.setOrderType(retailOrder.getType().equals(1) ? OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey());
            orderFullDate.setOrderNo(retailOrder.getId());
            orderFullDate.setOrderTime(retailOrder.getTheTime());
            orderFullDate.setExamineTime(retailOrder.getExamineTime());
            orderFullDate.setCustomerId(retailOrder.getCustomerId());
            orderFullDate.setCustomerName(retailOrder.getCustomerName());
            orderFullDate.setCustomerNumber(retailOrder.getCustomerNumber());
            orderFullDate.setMaterialId(retailOrderItem.getMaterialId());
            orderFullDate.setMaterialCode(retailOrderItem.getMaterialCode());
            orderFullDate.setMaterialName(retailOrderItem.getMaterialName());
            orderFullDate.setMaterialOldNumber(retailOrderItem.getMaterialOldNumber());
            orderFullDate.setSpecification(retailOrderItem.getSpecification());
            orderFullDate.setOrderNum(refundQty);
            orderFullDate.setOrderItemId(retailOrderItem.getId());

            BigDecimal price = new BigDecimal(0);

            if (refundQty.equals(retailOrderItem.getQty())) {
                price = retailOrderItem.getTotalAmount();
            } else {
                price = retailOrderItem.getTotalAmount()
                        .divide(Convert.toBigDecimal(retailOrderItem.getQty()))
                        .multiply(Convert.toBigDecimal(refundQty));
            }

            orderFullDate.setPayAmount(price);


            orderFullDate.setFullCost(betweenDay < 15 ? price.multiply(Constant.STORAGE_FEE_ONE).setScale(2, BigDecimal.ROUND_HALF_UP)
                    : price.multiply(Constant.STORAGE_FEE_TWO).setScale(2, BigDecimal.ROUND_HALF_UP));

            orderFullDate.setCustomerWalletId(retailOrderItem.getCustomerWalletId());
            orderFullDate.setCustomerWalletName(retailOrderItem.getCustomerWalletName());
            orderFullDate.setCustomerWalletNumber(retailOrderItem.getCustomerWalletNumber());
            orderFullDate.setK3CategoryId(retailOrderItem.getK3CategoryId());
            orderFullDate.setK3CategoryName(retailOrderItem.getK3CategoryName());
            orderFullDate.setK3CategoryNumber(retailOrderItem.getK3CategoryNumber());
            orderFullDate.setFullStartTime(retailOrderItem.getFullTime());


            orderFullDate.setFullEndTime(DateUtil.beginOfDay(parse));

            orderFullDate.setFullNum(Convert.toInt(betweenDay));
            orderFullDate.setCostId(costId);

            orderFullDate.insert();


            RetailOrderItem retailOrderItem1 = new RetailOrderItem();
            retailOrderItem1.setId(retailOrderItem.getId());
            retailOrderItem1.setFullNum(betweenDay);
            retailOrderItem1.setFullTime(betweenDay == 1 ? parse : null);
            retailOrderItem1.updateById();


        }


    }

}
