package com.sifang.modules.supply.order.service;

import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.customer.constant.SourceConstants;
import com.sifang.modules.platform.utils.PlantformUtils;
import com.sifang.modules.sunshine.SystemSetting.dao.ProjectSettingDao;
import com.sifang.modules.sunshine.SystemSetting.entity.CrmProjectSetting;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.supply.order.constant.ApplyOrderConstants;
import com.sifang.modules.supply.order.dao.*;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialApply;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialApplyDetail;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialApplyGather;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialApplyMsg;
import com.sifang.modules.supply.order.request.ApplyOrderDetailReq;
import com.sifang.modules.supply.order.request.ApplyOrderReq;
import com.sifang.modules.supply.stock.dao.SupplyMaterialDao;
import com.sifang.modules.supply.stock.entity.SupplyMaterial;
import com.sifang.modules.sys.entity.Operator;
import com.sifang.modules.sys.util.CrmUtils;
import com.sifang.modules.sys.util.LayuiPage;
import com.sifang.modules.sys.util.SqlBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author hongzq
 */
@Service
public class MaterialApplyService {

    @Autowired
    SupplyMaterialDao materialDao;
    @Autowired
    MaterialApplyDao materialApplyDao;
    @Autowired
    MaterialApplyMsgDao materialApplyMsgDao;

    @Autowired
    MaterialApplyDetailDao materialApplyDetailDao;
    @Autowired
    MaterialApplyGatherDao materialApplyGatherDao;
    @Autowired
    ProjectSettingDao projectSettingDao;

    @Autowired
    SupplyOrderAuditDao supplyOrderDao;

    public Record getRecordById(String id, Operator operator) {
        Map<String, String> map = Maps.newHashMap();
        map.put("applyId", id);
        List<Record> orderList = materialApplyDao.applyOrderList(null, map, operator);
        return orderList.isEmpty() ? null : orderList.get(0);
    }

    public List<Record> listGatherByApplyId(String id) {
        return materialApplyGatherDao.listGatherByApplyId(id);
    }

    public List<Record> listDetailsByApplyId(String id) {
        return materialApplyDetailDao.listByApplyId(id);
    }

    public List<CrmSupplyMaterialApplyMsg> listMsgByApplyId(String id) {
        return materialApplyMsgDao.listMsgByApplyId(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveApplyOrder(ApplyOrderReq req, Operator operator) {
        String id = req.getId();
        if (StrKit.isBlank(id)) {
            addApplyOrder(req, operator);
        } else {
            editApplyOrder(req, operator);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void modifyApplyOrder(ApplyOrderReq req, Operator operator){
        //仅待匹配的订单可以修改
        CrmSupplyMaterialApply apply = materialApplyDao.get(req.getId());
        if (!ApplyOrderConstants.WAIT_MATCH.equals(apply.getStatus())) {
            throw new BusinessException("仅待匹配的订单可以修改");
        }
        //删除物料汇总
        materialApplyGatherDao.deleteByApplyId(apply.getId());
        //删除物料明细表
        materialApplyDetailDao.deleteByApplyId(apply.getId());
        //添加汇总表
        List<CrmSupplyMaterialApplyGather> gatherList = addGatherList(req.getDetails(), apply.getId());
        //添加明细表
        List<CrmSupplyMaterialApplyDetail> detailList = addMaterialDetails(gatherList, apply.getId());

        setTotalData(apply, detailList);

        materialApplyDao.save(apply);
        //操作记录
        materialApplyMsgDao.saveOptMsg(apply.getId(), ApplyOrderConstants.OPT_EDIT, "", operator);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteApplyOrder(String ids, Operator operator) {
        for (String id : ids.split(",")) {
            CrmSupplyMaterialApply applyOrder = materialApplyDao.get(id);
            if (!ApplyOrderConstants.AUDIT_FAIL.equals(applyOrder.getStatus())) {
                throw new BusinessException("仅审核未通过的订单支持删除");
            }
            applyOrder.setStatus(ApplyOrderConstants.DELETED);
            materialApplyDao.save(applyOrder);
            //操作记录
            materialApplyMsgDao.saveOptMsg(applyOrder.getId(), ApplyOrderConstants.OPT_DELETED, "", operator);
        }
    }

    private void addApplyOrder(ApplyOrderReq req, Operator operator) {
        CrmSupplyMaterialApply apply = new CrmSupplyMaterialApply();
        apply.setNumber(PlantformUtils.findOrderNumber("WL"));
        setCommonFields(req, apply);
        apply.setCreateTime(new Date());
        apply.setCreateBy(operator.getUserId());
        apply.setCreator(operator.getUserName());
        apply.setTraderId(CrmUtils.getCurrentTraderId(operator.getUserId()));
        //1.待业务员审批
        apply.setStatus(ApplyOrderConstants.WAIT_YW_AUDIT);
        materialApplyDao.save(apply);

        //添加汇总表
        List<CrmSupplyMaterialApplyGather> gatherList = addGatherList(req.getDetails(), apply.getId());
        //添加明细表
        List<CrmSupplyMaterialApplyDetail> detailList = addMaterialDetails(gatherList, apply.getId());
        setTotalData(apply, detailList);
        materialApplyDao.save(apply);
        //操作记录
        materialApplyMsgDao.saveOptMsg(apply.getId(), ApplyOrderConstants.OPT_CREATE, "", operator);
    }

    private void setCommonFields(ApplyOrderReq req, CrmSupplyMaterialApply apply) {

        apply.setPersonInCharge(req.getPersonInCharge());
        apply.setMobile(req.getMobile());
        apply.setProvince(req.getProvince());
        apply.setCity(req.getCity());
        apply.setArea(req.getArea());
        apply.setAddress(req.getAddress());
        apply.setInWarehouseId(req.getInWarehouseId());

        apply.setRemark(req.getRemark());
    }

    private void editApplyOrder(ApplyOrderReq req, Operator operator) {
        CrmSupplyMaterialApply apply = materialApplyDao.get(req.getId());
        setCommonFields(req, apply);
        //1.待业务员审批
        apply.setStatus(SourceConstants.ONE);

        //删除物料汇总
        materialApplyGatherDao.deleteByApplyId(apply.getId());
        //删除物料明细表
        materialApplyDetailDao.deleteByApplyId(apply.getId());
        //添加汇总表
        List<CrmSupplyMaterialApplyGather> gatherList = addGatherList(req.getDetails(), apply.getId());
        //添加明细表
        List<CrmSupplyMaterialApplyDetail> detailList = addMaterialDetails(gatherList, apply.getId());

        setTotalData(apply, detailList);

        materialApplyDao.save(apply);
        //操作记录
        materialApplyMsgDao.saveOptMsg(apply.getId(), ApplyOrderConstants.OPT_EDIT, "", operator);
    }

    void setTotalData(CrmSupplyMaterialApply apply, List<CrmSupplyMaterialApplyDetail> detailList) {
        BigDecimal total = BigDecimal.ZERO;
        for (CrmSupplyMaterialApplyDetail detail : detailList) {
            total = total.add(detail.getApplyAmount());
        }
        apply.setMaterialTypeAmount(new BigDecimal(detailList.size()));
        apply.setTotalApplyAmount(total);
    }

    private List<CrmSupplyMaterialApplyGather> addGatherList(List<ApplyOrderDetailReq> details, String applyId) {
        List<CrmSupplyMaterialApplyGather> gatherList = new ArrayList<>();
        for (int i = 0; i < details.size(); i++) {
            ApplyOrderDetailReq detailReq = details.get(i);
            if (detailReq.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BusinessException("申请数量需要大于0");
            }
            CrmSupplyMaterialApplyGather detail = new CrmSupplyMaterialApplyGather();
            detail.setTargetId(detailReq.getTargetId());
            detail.setApplyId(applyId);
            detail.setAmount(detailReq.getAmount());
            detail.setBeforeAmount(detailReq.getAmount());

            detail.setSort(i + 1);
            gatherList.add(detail);
        }
        materialApplyGatherDao.save(gatherList);
        return gatherList;
    }

    List<CrmSupplyMaterialApplyGather> modifyGatherListForAudit(List<ApplyOrderDetailReq> details) {
        List<CrmSupplyMaterialApplyGather> gatherList = new ArrayList<>();
        for (ApplyOrderDetailReq detailReq : details) {
            if (detailReq.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BusinessException("申请数量需要大于0");
            }
            CrmSupplyMaterialApplyGather detail = materialApplyGatherDao.get(detailReq.getDetailId());
            detail.setAmount(detailReq.getAmount());
            //工程师审核后数量
            detail.setAfterAmount(detailReq.getAmount());
            gatherList.add(detail);
        }
        materialApplyGatherDao.save(gatherList);
        return gatherList;
    }

    List<CrmSupplyMaterialApplyDetail> addMaterialDetails(List<CrmSupplyMaterialApplyGather> gatherList, String applyId) {
        //添加物料明细
        List<CrmSupplyMaterialApplyDetail> detailList = new ArrayList<>();
        for (CrmSupplyMaterialApplyGather gather : gatherList) {
          if (SourceConstants.ONE.equals(gather.getType())) {
                Record material = materialDao.findById(gather.getTargetId());
                if (!(SourceConstants.ONE.equals(material.getStr("status")) && "0".equals(material.getStr("support_apply")))) {
                    throw new BusinessException("物料" + material.getStr("code") + "不支持申请");
                }
                addDetails(detailList, material.getStr("id"), gather.getAmount(), applyId);
            }
        }
        if (detailList.isEmpty()) {
            throw new BusinessException("物料明细不能为空");
        }
        materialApplyDetailDao.save(detailList);
        return detailList;
    }

    void addDetails(List<CrmSupplyMaterialApplyDetail> list, String materialId, BigDecimal applyAmount, String applyId) {
        boolean exist = false;
        for (CrmSupplyMaterialApplyDetail detail : list) {
            if (detail.getMaterialId().equals(materialId)) {
                exist = true;
                detail.setApplyAmount(detail.getApplyAmount().add(applyAmount));
                break;
            }
        }
        if (!exist) {
            CrmSupplyMaterialApplyDetail applyDetail = new CrmSupplyMaterialApplyDetail();
            applyDetail.setApplyId(applyId);
            applyDetail.setMaterialId(materialId);
            applyDetail.setApplyAmount(applyAmount);
            applyDetail.setSort(list.size() + 1);
            list.add(applyDetail);
        }
    }

    public void applyOrderListPage(LayuiPage<Record> page, Map<String, String> map, Operator operator) {
        page.setData(materialApplyDao.applyOrderList(page, map, operator));
        page.setCount(materialApplyDao.countApplyOrderList(map, operator));
    }

    public List<Record> findCanApplyMaterials(String code, String desc, String materialTypeId) {
        if (StrKit.isBlank(code) && StrKit.isBlank(desc)) {
            return new ArrayList<>();
        }
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("desc", desc);
        map.put("materialTypeId", materialTypeId);
        return findCanApplyMaterialsByKeyWord(map, null);
    }

    public List<Record> findCanApplyMaterialsByKeyWord(Map<String, String> map, LayuiPage page) {
        SqlBuilder builder = new SqlBuilder();
        builder.line("select m.id, m.code, t.name as material_type, m.material_name, m.material_specs,m.material_brand,m.material_attribute as type,m.unit_name,m.unit,m.remarks ")
                .line("from crm_supply_material m ")
                .line("left join crm_supply_material_type t on m.material_type_id=t.id")
                .line("where m.status='1'");
        if (StringUtil.checkParamsValid(map.get("code"))) {
            builder.like("and m.code like ?", map.get("code"));
        }

        if (StringUtil.checkParamsValid(map.get("materialTypeId"))) {
            builder.line("and m.material_type_id=?", map.get("materialTypeId"));
        }
        if (StringUtil.checkParamsValid(map.get("ids"))) {
            builder.inst("and m.id in", map.get("ids").split(","));
        }
        if (StringUtil.checkParamsValid(map.get("attribute"))) {
            builder.line("and m.material_attribute=?", map.get("attribute"));
        }
        if (page != null) {
            builder.limit(page.getPage(), page.getLimit());
        }
        List<Record> materialList = Db.find(builder.build(), builder.params());

        return materialList;
    }

    public List<Record> getOrderDetail(String id,String type){
        return supplyOrderDao.getOrderDetail(id,type);
    }
    //订单详情
    public Record orderDetail(String id){
        Record record=supplyOrderDao.orderDetail(id);
        return record;
    }
    public List<Record> findMaterialsByKeyWord(Map<String, String> map, LayuiPage page) {

        SqlBuilder builder = new SqlBuilder();
        builder.line("select m.id, m.code, t.name as material_type, m.remarks")
                .line("from crm_supply_material m")
                .line("left join crm_supply_material_type t on m.material_type_id=t.id")
                .line("left join crm_supply_material_warehouse_stocks s ON m.`id` = s.`material_id` and s.`warehouse_id` = ?", map.get("warehouseId"))
                .line("where m.status='1'");
        if (StringUtil.checkParamsValid(map.get("code"))) {
            builder.like("and m.code like ?", map.get("code"));
        }
        if (StringUtil.checkParamsValid(map.get("desc"))) {

            builder.like("and (m.remarks like ?", map.get("desc"));
            builder.like("or m.code like ? )", map.get("desc"));
        }
        if (StringUtil.checkParamsValid(map.get("materialGroupId"))) {
            builder.line("and m.material_group_id=?", map.get("materialGroupId"));
        }
        if (StringUtil.checkParamsValid(map.get("materialTypeId"))) {
            builder.line("and m.material_type_id=?", map.get("materialTypeId"));
        }
        if (StringUtil.checkParamsValid(map.get("ids"))) {
            builder.inst("and m.id in", map.get("ids").split(","));
        }
        if (StringUtil.checkParamsValid(map.get("stock")) && "0".equals(map.get("stock"))) {
            builder.line("and s.`warning` > 0");
        }
        if (page != null) {
            builder.limit(page.getPage(), page.getLimit());
        }
        List<Record> materialList = Db.find(builder.build(), builder.params());
        return materialList;
    }

    public List<String> findElectricMaterialDate(String type) {
        if (StrKit.isBlank(type) ) {
            return new ArrayList<>();
        }
        SqlBuilder builder = new SqlBuilder();
        builder.line("select DISTINCT(model) ")
                .line("from crm_electric_set ")
                .line("where type = ? and status = '0'  ORDER BY model ASC ",type);
        return Db.query(builder.build(), builder.params());
    }

    public List<String> findElectricMaterial2Date(String typeId) {
        if (StrKit.isBlank(typeId) ) {
            return new ArrayList<>();
        }
        SqlBuilder builder = new SqlBuilder();
        builder.line("SELECT DISTINCT a.material_specs ")
                .line("FROM crm_supply_material a ")
                .line("WHERE a.status = '1' AND a.material_type_id=?",typeId);
        return Db.query(builder.build(), builder.params());
    }

    public BigDecimal fingMaterialPrice(String specs,String materialType,String qqProjectCode){
       return materialDao.getMaxPriceBySpec2(materialType,specs,qqProjectCode);
    }

    public SupplyMaterial fingMaterialById(String id){
        return materialDao.get(id);
    }
}
