package cn.ibizlab.core.sample.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.math.BigInteger;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.util.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import cn.ibizlab.util.errors.BadRequestAlertException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Lazy;
import cn.ibizlab.core.sample.domain.IBIZOrder;
import cn.ibizlab.core.sample.filter.IBIZOrderSearchContext;
import cn.ibizlab.core.sample.service.IIBIZOrderService;

import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.helper.DEFieldCacheMap;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.ibizlab.core.sample.mapper.IBIZOrderMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.StringUtils;

/**
 * 实体[订单] 服务对象接口实现
 */
@Slf4j
@Service("IBIZOrderServiceImpl")
public class IBIZOrderServiceImpl extends ServiceImpl<IBIZOrderMapper, IBIZOrder> implements IIBIZOrderService {

    @Autowired
    @Lazy
    protected cn.ibizlab.core.sample.service.IIBIZOrderDetailService ibizorderdetailService;
    @Autowired
    @Lazy
    protected cn.ibizlab.core.sample.service.IIBIZCustomerService ibizcustomerService;

    protected int batchSize = 500;

    @Override
    @Transactional
    public boolean create(IBIZOrder et) {
        fillParentData(et);
        if(!this.retBool(this.baseMapper.insert(et)))
            return false;
        CachedBeanCopier.copy(get(et.getIbizorderid()),et);
        return true;
    }

    @Override
    @Transactional
    public void createBatch(List<IBIZOrder> list) {
        list.forEach(item->fillParentData(item));
        this.saveBatch(list,batchSize);
    }

    @Override
    @Transactional
    public IBIZOrder createTemp(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder createTempMajor(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public boolean update(IBIZOrder et) {
        fillParentData(et);
         if(!update(et,(Wrapper) et.getUpdateWrapper(true).eq("ibizorderid",et.getIbizorderid())))
            return false;
        CachedBeanCopier.copy(get(et.getIbizorderid()),et);
        return true;
    }

    @Override
    @Transactional
    public void updateBatch(List<IBIZOrder> list) {
        list.forEach(item->fillParentData(item));
        updateBatchById(list,batchSize);
    }

    @Override
    @Transactional
    public IBIZOrder updateTemp(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder updateTempMajor(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public boolean remove(String key) {
        if(!ObjectUtils.isEmpty(ibizorderdetailService.selectByIbizorderid(key)))
            throw new BadRequestAlertException("删除数据失败，当前数据存在关系实体[IBIZOrderDetail]数据，无法删除!","","");
        boolean result=removeById(key);
        return result ;
    }

    @Override
    @Transactional
    public void removeBatch(Collection<String> idList) {
        if(!ObjectUtils.isEmpty(ibizorderdetailService.selectByIbizorderid(idList)))
            throw new BadRequestAlertException("删除数据失败，当前数据存在关系实体[IBIZOrderDetail]数据，无法删除!","","");
        removeByIds(idList);
    }

    @Override
    @Transactional
    public IBIZOrder removeTemp(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder removeTempMajor(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder get(String key) {
        IBIZOrder et = getById(key);
        if(et==null){
            et=new IBIZOrder();
            et.setIbizorderid(key);
        }
        else{
        }
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder getTemp(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder getTempMajor(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    public IBIZOrder getDraft(IBIZOrder et) {
        fillParentData(et);
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder getDraftTemp(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder getDraftTempMajor(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    @Transactional
    public IBIZOrder bUIAction(IBIZOrder et) {
        //自定义代码
        return et;
    }

    @Override
    public boolean checkKey(IBIZOrder et) {
        return (!ObjectUtils.isEmpty(et.getIbizorderid()))&&(!Objects.isNull(this.getById(et.getIbizorderid())));
    }
    @Override
    @Transactional
    public boolean save(IBIZOrder et) {
        if(!saveOrUpdate(et))
            return false;
        return true;
    }

    @Override
    @Transactional
    public boolean saveOrUpdate(IBIZOrder et) {
        if (null == et) {
            return false;
        } else {
            return checkKey(et) ? this.update(et) : this.create(et);
        }
    }

    @Override
    @Transactional
    public boolean saveBatch(Collection<IBIZOrder> list) {
        list.forEach(item->fillParentData(item));
        saveOrUpdateBatch(list,batchSize);
        return true;
    }

    @Override
    @Transactional
    public void saveBatch(List<IBIZOrder> list) {
        list.forEach(item->fillParentData(item));
        saveOrUpdateBatch(list,batchSize);
    }


	@Override
    public List<IBIZOrder> selectByIbizcustomerid(String ibizcustomerid) {
        return baseMapper.selectByIbizcustomerid(ibizcustomerid);
    }
    @Override
    public void removeByIbizcustomerid(String ibizcustomerid) {
        this.remove(new QueryWrapper<IBIZOrder>().eq("ibizcustomerid",ibizcustomerid));
    }


    /**
     * 查询集合 测试打印
     */
    @Override
    public Page<IBIZOrder> searchCSDY(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchCSDY(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 当前用户已审核
     */
    @Override
    public Page<IBIZOrder> searchCurState30(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchCurState30(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 订单金额统计报表
     */
    @Override
    public Page<IBIZOrder> searchDDJETJBB(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchDDJETJBB(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 订单报表打印
     */
    @Override
    public Page<IBIZOrder> searchDDReport(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchDDReport(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 打印订单明细数据源
     */
    @Override
    public Page<IBIZOrder> searchDYDDMXSJY(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchDYDDMXSJY(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 DEFAULT
     */
    @Override
    public Page<IBIZOrder> searchDefault(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchDefault(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 图表默认数据源
     */
    @Override
    public Page<IBIZOrder> searchEchartsDefaultDataSource(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchEchartsDefaultDataSource(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 仪表盘数据源
     */
    @Override
    public Page<IBIZOrder> searchGaugeDataSource(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchGaugeDataSource(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 仪表数据源（时间）
     */
    @Override
    public Page<IBIZOrder> searchGaugeDataSourceByTime(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchGaugeDataSourceByTime(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 当前用户审核通过与全部取消
     */
    @Override
    public Page<IBIZOrder> searchLOGIC_22(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchLOGIC_22(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 雷达图数据源
     */
    @Override
    public Page<IBIZOrder> searchRadarDataSource(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchRadarDataSource(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 审核中订单
     */
    @Override
    public Page<IBIZOrder> searchSHZOrder(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchSHZOrder(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 订单状态10
     */
    @Override
    public Page<IBIZOrder> searchState10(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchState10(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 订单状态30
     */
    @Override
    public Page<IBIZOrder> searchState30(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchState30(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 订单状态40
     */
    @Override
    public Page<IBIZOrder> searchState40(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchState40(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }

    /**
     * 查询集合 小额查询
     */
    @Override
    public Page<IBIZOrder> searchXECX(IBIZOrderSearchContext context) {
        fillWFTaskContext(context);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<IBIZOrder> pages=baseMapper.searchXECX(context.getPages(),context,context.getSelectCond());
        return new PageImpl<IBIZOrder>(pages.getRecords(), context.getPageable(), pages.getTotal());
    }


    @Autowired
    private cn.ibizlab.util.client.IBZWFFeignClient ibzwfFeignClient;

    /**
     * 查询工作流待办
     * @param context
     */
    private void fillWFTaskContext(IBIZOrderSearchContext context){

        if(!StringUtils.isEmpty(context.getUserTaskId()) && !StringUtils.isEmpty(context.getProcessDefinitionKey())){
            List<String> businessKeys= ibzwfFeignClient.getbusinesskeysByUserId("demosys", cn.ibizlab.util.security.AuthenticationUser.getAuthenticationUser().getUserid(),"ibizorders",context.getProcessDefinitionKey(),context.getUserTaskId());
            if(businessKeys.size()>0){
                context.getSelectCond().in("ibizorderid",businessKeys);
            }
            else{
                context.getSelectCond().apply("1<>1");
            }
        }
    }

    /**
     * 为当前实体填充父数据（外键值文本、外键值附加数据）
     * @param et
     */
    private void fillParentData(IBIZOrder et){
        //实体关系[DER1N_IBIZORDER_IBIZCUSTOMER_IBIZCUSTOMERID]
        if(!ObjectUtils.isEmpty(et.getIbizcustomerid())){
            cn.ibizlab.core.sample.domain.IBIZCustomer ibizcustomer=et.getIbizcustomer();
            if(ObjectUtils.isEmpty(ibizcustomer)){
                cn.ibizlab.core.sample.domain.IBIZCustomer majorEntity=ibizcustomerService.get(et.getIbizcustomerid());
                et.setIbizcustomer(majorEntity);
                ibizcustomer=majorEntity;
            }
            et.setIbizcustomername(ibizcustomer.getIbizcustomername());
        }
    }




    @Override
    public List<JSONObject> select(String sql, Map param){
        return this.baseMapper.selectBySQL(sql,param);
    }

    @Override
    @Transactional
    public boolean execute(String sql , Map param){
        if (sql == null || sql.isEmpty()) {
            return false;
        }
        if (sql.toLowerCase().trim().startsWith("insert")) {
            return this.baseMapper.insertBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith("update")) {
            return this.baseMapper.updateBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith("delete")) {
            return this.baseMapper.deleteBySQL(sql,param);
        }
        log.warn("暂未支持的SQL语法");
        return true;
    }

    @Override
    public List<IBIZOrder> getIbizorderByIds(List<String> ids) {
         return this.listByIds(ids);
    }

    @Override
    public List<IBIZOrder> getIbizorderByEntities(List<IBIZOrder> entities) {
        List ids =new ArrayList();
        for(IBIZOrder entity : entities){
            Serializable id=entity.getIbizorderid();
            if(!ObjectUtils.isEmpty(id)){
                ids.add(id);
            }
        }
        if(ids.size()>0)
           return this.listByIds(ids);
        else
           return entities;
    }

    @Autowired
    @Lazy
    IIBIZOrderService proxyService;

    @Value("${ibiz.syncImportLimit:1000}")
    private int syncImportLimit;

    /**
     * 上传数据检查
     * @param entities
     * @param isIgnoreError
     * @return
     */
    private JSONObject testImportData(List<IBIZOrder> entities,boolean isIgnoreError) {

        JSONObject rs=new JSONObject();
        Set ids=new HashSet<>();
        List<String> errorMsgs = new ArrayList<>();
        List<Integer> errorLines = new ArrayList<>();
        List<IBIZOrder> duplicateKeys=new ArrayList<>();
        String keyField= DEFieldCacheMap.getDEKeyField(IBIZOrder.class);
        if(ObjectUtils.isEmpty(keyField)){
            errorLines.add(1);
            rs.put("rst", 1);
            rs.put("msg", "数据导入失败，未能获取到实体[IBIZOrder]的主键属性");
            rs.put("errorLines", errorLines);
            return rs;
        }
        //主键重复性判断.外键约束判断（上传数据自身的检查/数据库的检查）
        for(int i=0;i<entities.size();i++) {
            IBIZOrder entity = entities.get(i);
            Object id = entity.getIbizorderid();
            if(ObjectUtils.isEmpty(id)) {
                id = entity.getDefaultKey(true);
                if(ObjectUtils.isEmpty(id)){
                    Integer lineNum = i + 1;
                    errorLines.add(lineNum);
                    errorMsgs.add("第" + lineNum + "行：无法获取当前数据主键。");
                    continue;
                }
                else{
                    entity.setIbizorderid((String) id);
                }
            }
            if(!ids.contains(id)){
                ids.add(id);
            }
            else{
                Integer lineNum = i + 1;
                errorLines.add(lineNum);
                errorMsgs.add("第" + lineNum + "行：导入数据之间存在重复数据。");
                if(isIgnoreError){
                    duplicateKeys.add(entity);
                    continue;
                }
                else{
                    break;
                }
            }
        //实体关系[DER1N_IBIZORDER_IBIZCUSTOMER_IBIZCUSTOMERID]
        if(!ObjectUtils.isEmpty(entity.getIbizcustomerid())){
            cn.ibizlab.core.sample.domain.IBIZCustomer fkEntity=new cn.ibizlab.core.sample.domain.IBIZCustomer();
            fkEntity.setIbizcustomerid(entity.getIbizcustomerid());
            if(!ibizcustomerService.checkKey(fkEntity)){
                Integer lineNum = i + 1;
                errorLines.add(lineNum);
                errorMsgs.add(String.format("第" + lineNum + "行：[%s]父数据有误。",entity.getIbizcustomerid()));
                if(isIgnoreError){
                    entity.setIbizcustomerid(null);
                    continue;
                }
                else{
                   break;
                }
            }
        }
        }
        if(duplicateKeys.size()>0){
            for(IBIZOrder duplicateKey:duplicateKeys){
                entities.remove(duplicateKey);
            }
        }
        if (errorMsgs.size() > 0) {
            rs.put("rst", 1);
            rs.put("msg", String.join("<br>", errorMsgs));
            rs.put("errorLines", errorLines);
            return rs;
        }
        rs.put("rst", 0);
        return rs;
    }

    /**
     * 实体数据导入
     * @param entities
     * @param batchSize
     * @param isIgnoreError
     * @return
     */
    @Override
    @Transactional
    public JSONObject importData(List<IBIZOrder> entities, int batchSize ,boolean isIgnoreError) {
        if(entities.size()>syncImportLimit){
            proxyService.asyncImportData(entities,batchSize,isIgnoreError);
            JSONObject rs=new JSONObject();
            rs.put("rst", 0);
            rs.put("msg",String.format("当前导入数据已超过同步导入数量上限[%s]，系统正在进行异步导入，请稍后!",syncImportLimit));
            rs.put("data",entities);
            return rs;
        }
        else{
            return syncImportData(entities,batchSize,isIgnoreError);
        }
    }

    @Transactional
    public void asyncImportData(List<IBIZOrder> entities, int batchSize ,boolean isIgnoreError){
        executeImportData(entities,batchSize,isIgnoreError);
    }

    @Transactional
    public JSONObject syncImportData(List<IBIZOrder> entities, int batchSize ,boolean isIgnoreError){
        return executeImportData(entities,batchSize,isIgnoreError);
    }

    @Transactional
    public JSONObject executeImportData(List<IBIZOrder> entities, int batchSize ,boolean isIgnoreError) {
        JSONObject rs=testImportData(entities,isIgnoreError);
        if(rs.getInteger("rst")==1 && !isIgnoreError)
            return rs;
        List<IBIZOrder> tempDEList=new ArrayList<>();
        Set tempIds=new HashSet<>();

        for(int i=0;i<entities.size();i++) {
            IBIZOrder entity = entities.get(i);
            tempDEList.add(entity);
            Object id=entity.getIbizorderid();
            if(!ObjectUtils.isEmpty(id))
                tempIds.add(id);
            if(tempDEList.size()>=batchSize || (tempDEList.size()<batchSize && i==entities.size()-1)){
                commit(tempDEList,tempIds);
                tempDEList.clear();
                tempIds.clear();
                }
            }
        rs.put("rst", 0);
        rs.put("data",entities);
        return rs;
    }

    /**
     * 批量提交
     * @param entities 数据
     * @param ids 要提交数据的id
     */
    @Transactional
    public void commit(List<IBIZOrder> entities, Set ids){
        List<IBIZOrder> _create=new ArrayList<>();
        List<IBIZOrder> _update=new ArrayList<>();
        Set oldIds=new HashSet<>();
        if(ids.size()>0){
            List<IBIZOrder> oldEntities=this.listByIds(ids);
            for(IBIZOrder entity:oldEntities){
                oldIds.add(entity.getIbizorderid());
            }
        }
        for(IBIZOrder entity:entities){
            Object id=entity.getIbizorderid();
            if(oldIds.contains(id))
                _update.add(entity);
            else
                _create.add(entity);
        }
        if(_update.size()>0)
            proxyService.updateBatch(_update);
        if(_create.size()>0)
            proxyService.createBatch(_create);
    }



    /**
     * 获取searchContext
     * @return
     */
    public IBIZOrderSearchContext getSearchContext(){
        return new IBIZOrderSearchContext();
    }
}



