package com.sifang.modules.flowpath.service;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.flowable.service.ProcessFlowableService;
import com.sifang.modules.flowable.utils.FormUtils;
import com.sifang.modules.flowpath.constant.BondApplyConstant;
import com.sifang.modules.flowpath.dao.CashOutApplyDao;
import com.sifang.modules.flowpath.entity.CashOutApply;
import com.sifang.modules.flowpath.vo.CashOutVo;
import com.sifang.modules.platform.utils.PlantformUtils;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.sys.common.UserUtils;
import com.sifang.modules.sys.common.entity.User;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.DateUtils;
import com.sifang.modules.sys.common.utils.IdGen;
import com.sifang.modules.sys.util.CrmUtils;
import com.sifang.modules.sys.util.LayuiPage;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
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.Date;
import java.util.List;
import java.util.Map;

@Service
public class CashOutApplyService extends BaseService {

    @Autowired
    private CashOutApplyDao cashOutApplyDao;

    @Autowired
    private ProcessFlowableService flowableService;

    @Autowired
    TaskService taskService;

    public void cashOutApplyList(LayuiPage page, Map<String,String> map){
        User user = UserUtils.getUser();
        List<Record> list=cashOutApplyDao.cashOutApplyList(page, map, user);
        page.setData(list);
    }

    public Record getTraderCanOutCash(String traderId){
        logger.info(">>>>>>>>>>>>>>getTraderCanOutCash traderId；{}",traderId);
        Record record=cashOutApplyDao.getTraderCanOutCash(traderId);
        return record;
    }

    public Record getDetailById(String id){
       Record record=cashOutApplyDao.getDetailById(id);
       return record;
    }

    //保存申请
    @Transactional(rollbackFor = Exception.class)
    public void saveCashOutApply(CashOutVo vo){
       logger.info(">>>>>>>>>>>>>>>>>>>saveCashOutApply  vo:{}",vo.toString());
        User user = UserUtils.getUser();
        String userName=user.getUserName();
        Date date=new Date();
        if(vo.getOutCash().compareTo(BigDecimal.ZERO)==0){
            throw new RuntimeException("请款金额不能为0!");
        }
        Record record=getTraderCanOutCash(vo.getTraderId());
        if(BondApplyConstant.JS_ACCOUNT.equals(vo.getObjType())){  //待结算账户
            if(record.getBigDecimal("settle_amount").compareTo(vo.getOutCash())<0){
                throw new RuntimeException("该账户可请款金额不足!");
            }
        }else{  //质保金账户
            if(record.getBigDecimal("qa_amount_usable").compareTo(vo.getOutCash())<0){
                throw new RuntimeException("该账户可请款金额不足!");
            }
        }
        CashOutApply apply;
        if(StringUtil.isBlank(vo.getId())){
             apply=new CashOutApply();
             apply.setApplyNumber(PlantformUtils.getOrderNumber());
             apply.setCreateBy(user.getId());
             apply.setCreateName(userName);
             apply.setCreateTime(date);
             apply.setDepartmentId(user.getDepartmentId());
             apply.setDepartmentName(user.getDepartmentName());

        }else{
            apply=cashOutApplyDao.getByApplyId(vo.getId());
            if(StringUtil.equalsAny(apply.getStatus(), BondApplyConstant.APPLYSTATUS_ONE,BondApplyConstant.APPLYSTATUS_TWO,BondApplyConstant.APPLYSTATUS_THREE)){
                throw new RuntimeException("该申请状态不允许修改!");
            }
        }

        apply.setSettleIds(vo.getSettleIds());
        apply.setAdjustmentApplyIds(vo.getAdjustmentApplyIds());

        apply.setTraderId(vo.getTraderId());
        apply.setObjType(vo.getObjType());
        apply.setOutCash(vo.getOutCash());
        apply.setCompanyName(vo.getCompanyName());
        apply.setBank(vo.getBank());
        apply.setBankCode(vo.getBankCode());
        apply.setRemarks(vo.getRemarks());
        apply.setVoucher(vo.getVoucher());

        if("0".equals(apply.getObjType())){
            apply.setOffsetBondAmount(vo.getOffsetBondAmount());
            apply.setPayAmount(vo.getPayAmount());
        }

        //将结算明细里面状态改成请款,将结算额调整 扣款的记录 改成已抵消
        cashOutApplyDao.updateSettleStatus(apply.getSettleIds(),"2");
        cashOutApplyDao.updateSettleApplyStatus(apply.getAdjustmentApplyIds(),"1");

        if(StringUtil.isBlank(vo.getId())){
            apply.setId(IdGen.uuid());
            Record rd = FormUtils.getdefLatest(FormUtils.CASH_OUT_APPLY);
            if(rd == null){
                throw  new RuntimeException("流程未定义，不可发布申请");
            }
            String traderName= CrmUtils.getTraderNameById(apply.getTraderId());
            String processName="请款申请-"+user.getUserName()+'-'+ DateUtils.formatDate(date,"yyyy-MM-dd HH:mm:ss")+"("+traderName+")";
            String processInstanceId=flowableService.startProcessFlowable(user,apply.getId(),rd,FormUtils.CASH_OUT_APPLY,date,userName,vo.getRemarks(),processName,apply.getTraderId());
            apply.setProcessInstanceId(processInstanceId);
            apply.setProcessDefId(rd.getStr("id"));

            apply.setOperateUserIds(user.getId()+","+rd.getStr("oneAuditUseId"));
            String taskName=FormUtils.getOneStepTaskName(rd.getStr("id"));
            apply.setTaskName(taskName);

            logger.info(">>>>>>>>>>>>>>>saveCashOutApply>>>>>>>>processInstanceId:{},taskName:{}",processInstanceId,taskName);
        }else if(StringUtil.isNotBlank(apply.getProcessInstanceId())){
            Task task = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
            flowableService.approveTask2(task,"编辑后提交",apply.getId(),user, FormUtils.CASH_OUT_APPLY);
        }
        apply.setStatus(BondApplyConstant.APPLYSTATUS_ONE);
        cashOutApplyDao.save(apply);
    }

    //删除申请
    @Transactional(rollbackFor = Exception.class)
    public void deleteCashOutApply(String id){
        logger.info(">>>>>>>>>>>deleteCashOutApply id:{}",id);
        User user = UserUtils.getUser();
        String userName= user.getUserName();
        //修改申请状态
        CashOutApply apply=cashOutApplyDao.getByApplyId(id);
        if(StringUtil.equalsAny(apply.getStatus(), BondApplyConstant.APPLYSTATUS_ONE,BondApplyConstant.APPLYSTATUS_TWO,BondApplyConstant.APPLYSTATUS_THREE)){
            throw new RuntimeException("申请状态不允许删除!");
        }
        apply.setStatus(BondApplyConstant.APPLYSTATUS_FOUR);
        cashOutApplyDao.save(apply);
        //将结算明细里面状态改成未请款,将结算额调整 扣款的记录 改成未抵消
        cashOutApplyDao.updateSettleStatus(apply.getSettleIds(),"0");
        cashOutApplyDao.updateSettleApplyStatus(apply.getAdjustmentApplyIds(),"0");
        //删除流程
        flowableService.deleteApplication(apply.getId(),apply.getProcessInstanceId(),userName,apply.getStatus(),FormUtils.CASH_OUT_APPLY);
    }

    //审批通过
    @Transactional(rollbackFor = Exception.class)
    public void examineCashOutApplyApprove(String id,String taskId,String content,String voucher){
        logger.info(">>>>>>>>>>>examineCashOutApplyApprove  id:{},taskId:{},Content:{}",id,taskId,content);
        User user = UserUtils.getUser();
        CashOutApply apply=cashOutApplyDao.getByApplyId(id);
        Record record=getTraderCanOutCash(apply.getTraderId());
        if(BondApplyConstant.JS_ACCOUNT.equals(apply.getObjType())){  //待结算账户
            if(record.getBigDecimal("settle_amount").compareTo(apply.getOutCash())<0){
                throw new IllegalArgumentException("该账户可请款金额不足!");
            }
        }else{  //质保金账户
            if(record.getBigDecimal("qa_amount_usable").compareTo(apply.getOutCash())<0){
                throw new IllegalArgumentException("该账户可请款金额不足!");
            }
        }

        Task task = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
        flowableService.approveTask2(task,content,apply.getId(),user, FormUtils.CASH_OUT_APPLY);
    }

    //审核驳回
    @Transactional(rollbackFor = Exception.class)
    public void rejectCashOutApplyTask(String id,String taskId,String content){
        logger.info(">>>>>>>>>>>rejectCashOutApplyTask  id:{},taskId:{},Content:{}",id,taskId,content);
        User user = UserUtils.getUser();
        CashOutApply apply=cashOutApplyDao.getByApplyId(id);
        apply.setContent(content);
        apply.setExamineOpinion(content);
        cashOutApplyDao.save(apply);

        Task task = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
        flowableService.rejectTask2(task,content,id,user,FormUtils.CASH_OUT_APPLY,apply.getCreateBy());

    }

    //获取请款金额
    public BigDecimal getStaticSettleAmount(String settleId){
        BigDecimal staticAmount=Db.queryBigDecimal(" SELECT IFNULL(SUM(d.amount),0) FROM `crm_trader_account_settle_detail` d WHERE d.id IN("+StringUtil.joinInSql(settleId.split(","))+") ");
        return staticAmount;
    }

    //请款的时候 获取结算额扣减 没有抵消的金额
    public Record getNoDeduct(String settleId){
        Record record=cashOutApplyDao.getNoDeduct(settleId);
        return record;
    }

    public long countSettleNoCash(String objType,String settleIds,String traderId){
        return Db.queryLong(" SELECT COUNT(d.id) FROM `crm_trader_account_settle_detail` d WHERE d.obj_type=?  AND d.type='2' AND trader_id=?   AND (d.flag ='0' OR d.flag IS NULL ) AND id NOT IN("+StringUtil.joinInSql(settleIds.split(","))+") ",objType,traderId);
    }

    public List<Record> getSettleDetails(String settleIds){
        List<Record> list=cashOutApplyDao.getCashOutSettleDetail(settleIds);
        return list;
    }

}
