package com.sifang.modules.customer.Service;

import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.account.dao.TraderAccountDao;
import com.sifang.modules.account.dao.TraderAccountSettleDetailDao;
import com.sifang.modules.account.entity.CrmTraderAccount;
import com.sifang.modules.account.entity.CrmTraderAccountSettleDetail;
import com.sifang.modules.changes.dao.CustomerEntrySurveyChangeRecordDao;
import com.sifang.modules.customer.constant.AccountSetConstants;
import com.sifang.modules.customer.dao.CrmAcceptingReportDetailDao;
import com.sifang.modules.customer.dao.CrmCustomerEntryDesignDao;
import com.sifang.modules.customer.dao.CrmCustomerEntryProjectDao;
import com.sifang.modules.customer.dao.CustomerEntryDao;
import com.sifang.modules.customer.entity.CrmAcceptingReport;
import com.sifang.modules.customer.entity.CrmAcceptingReportDetail;
import com.sifang.modules.customer.entity.CrmCustomerEntryDesign;
import com.sifang.modules.customer.entity.CustomerEntry;
import com.sifang.modules.platform.utils.PlantformUtils;
import com.sifang.modules.sunshine.SystemSetting.entity.CrmProjectSetting;
import com.sifang.modules.sunshine.SystemSetting.service.ProjectInfoSettingService;
import com.sifang.modules.sunshine.SystemSetting.service.SubconractorSettlementSchemeService;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sunshine.settleSet.dao.RewardsPunishWayDao;
import com.sifang.modules.sunshine.settleSet.entity.CrmRewardsPunishWay;
import com.sifang.modules.supply.warehouse.dao.CrmSupplyMaterialKeepDao;
import com.sifang.modules.sys.common.persistence.Parameter;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.DateUtils;
import com.sifang.modules.sys.entity.Operator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Map;

@Service
public class HuaRongMixRoofSettlementService extends BaseService {

    Logger logger= LoggerFactory.getLogger(getClass());

    @Autowired
    CustomerEntryDao customerDao;

    @Autowired
    private SubconractorSettlementSchemeService settlementSchemeService;

    @Autowired
    CustomerEntrySurveyChangeRecordDao surveyChangeRecordDao;

    @Autowired
    private AccountSetService accountSetService;

    @Autowired
    private TraderAccountDao accountDao;

    @Autowired
    private RewardsPunishWayDao rewardsPunishWayDao;

    @Autowired
    private TraderAccountSettleDetailDao accountSettleDetailDao;

    @Autowired
    private CrmSupplyMaterialKeepDao materialKeepDao;

    @Autowired
    private CustomerEntryService customerEntryService;

    @Autowired
    ProjectInfoSettingService projectService;

    @Autowired
    private CrmAcceptingReportDetailDao crmAcceptingReportDetailDao;

    @Autowired
    private CrmCustomerEntryProjectDao crmCustomerEntryProjectDao;

    @Autowired
    CrmCustomerEntryDesignDao crmCustomerEntryDesignDao;

    @Transactional(rollbackFor = Exception.class)
    public void addHuaRongSettlement(String projectIds[], String entryId) {
        for(String projectId : projectIds) {
            String roofType = crmCustomerEntryProjectDao.getRoofTypeByProjectId(entryId, projectId);
            CrmCustomerEntryDesign entryDesign = crmCustomerEntryDesignDao.findByEntryIdAndProjectId2(entryId, projectId);
            CrmAcceptingReportDetail acceptReport = crmAcceptingReportDetailDao.findByEntryIdAndProjectId(entryId, projectId);
            CustomerEntry entry = customerDao.get(entryId);
            CrmProjectSetting projectSetting = projectService.getById(projectId);
            //安装验收成功后，生成代理商的“预结算金额”，公式：预结算金额=分包结算金额*预结算比例；
            Map<String, String> map = settlementSchemeService.calcPriceByProjectId(projectId, acceptReport.getComponentNum(), acceptReport.getCapacity(), entry.getDistributorId(), entry);
            String settleNumber = map.get("number");//结算方案编号
            BigDecimal fbAmount = new BigDecimal(map.get("fbAmount"));
            //预结算比例，取系统设置下的值，未设置时，不可验收
            BigDecimal proportion = accountSetService.findYjsProportion(entry.getDistributorId());
            if (proportion == null) {
                throw new BusinessException("未设置预结算比例，不可操作验收");
            }

            BigDecimal yjsAmount = fbAmount.multiply(proportion).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            //代理商待结算账户下，生成变动明细，增加【分包款余额】的值
            CrmTraderAccountSettleDetail settleDetail = createSettleDetail(map, entry, yjsAmount, "0", "0", settleNumber, roofType, entryDesign, projectSetting);

            //释放标准授信额度余额、增加分包款余额、增加验收结算总额、增加质保金总额，增加冻结金额
            CrmTraderAccount account = accountDao.findByTraderId(entry.getDistributorId());
            BigDecimal totalAmount = customerEntryService.getTotalAmount(entry.getId(), "0");
            if (totalAmount != null && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                accountDao.updateBasicQuotaAmountBalance(totalAmount, account.getId());
            }
            BigDecimal cfAmount2 = BigDecimal.ZERO;
            //获取惩罚政策 单户装机容量≤10千瓦，基础结算价格每瓦减少0.15元
            CrmRewardsPunishWay rewardsPunishWay3 = rewardsPunishWayDao.getRewardsPunishWay("3");
            if (rewardsPunishWay3 != null) {
                BigDecimal cap = acceptReport.getCapacity().divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP); //运算后不要四舍五入
                logger.info("...单户装机容量 cap：{}", cap);
                if (cap.compareTo(new BigDecimal(rewardsPunishWay3.getHighData())) <= 0) {
                    //生成一条惩罚结算记录
                    cfAmount2 = acceptReport.getCapacity().multiply(new BigDecimal(rewardsPunishWay3.getRatioData())).multiply(proportion).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                    CrmTraderAccountSettleDetail cfSettleDetail2 = createSettleCfDetail(map, entry, cfAmount2.negate(), "5", "0", rewardsPunishWay3.getNumber(), rewardsPunishWay3.getRatioData(), roofType, entryDesign, projectSetting);
                    logger.info("..生成第二种惩罚记录金额 cfSettleDetail2:{},entryId:{}", cfSettleDetail2, entry.getId());
                    accountSettleDetailDao.save(cfSettleDetail2);
                }
            }
            BigDecimal settleAmount = yjsAmount.subtract(cfAmount2);
            BigDecimal settleAmountYsjs = yjsAmount;
            BigDecimal settleRewardsPunishAmount = cfAmount2;
            accountDao.updateAccountSettleAmount(settleAmount, settleAmountYsjs, settleRewardsPunishAmount, account.getId());
            accountDao.save(account);

            materialKeepDao.update("update CrmSupplyMaterialKeep set accountFlag='1' where sourceId=:p1 and type = '2' and accountFlag='0' ",
                    new Parameter(entry.getId()));
            if (settleDetail != null) {
                //保存结算明细
                accountSettleDetailDao.save(settleDetail);
                //将完工结算状态改为已结算
                entry.setWgSettleFlag("1");
                customerDao.save(entry);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void getHuaRongMixRoofSettlementBwSettleTask(String projectIds[], String entryId){
        CustomerEntry entry = customerDao.get(entryId);
        entry.setBwSettleFlag("1");
        customerDao.save(entry);
        for(String projectId : projectIds) {
            String roofType = crmCustomerEntryProjectDao.getRoofTypeByProjectId(entryId, projectId);
            CrmCustomerEntryDesign entryDesign = crmCustomerEntryDesignDao.findByEntryIdAndProjectId2(entryId, projectId);
            CrmAcceptingReportDetail acceptReport = crmAcceptingReportDetailDao.findByEntryIdAndProjectId(entryId, projectId);
            CrmProjectSetting projectSetting = projectService.getById(projectId);
            //生成结算记录
            //并网验收生成代理商的分包并网结算金额，分包并网结算额=分包结算额*（1-预结算比例A）-质保金，质保金=组件单瓦数*数量*质保金结算单价
            CrmAcceptingReport report = customerEntryService.getReportById(entry.getReceivingReportId());
            Map<String, String> map = settlementSchemeService.calcPriceByProjectId(projectId, acceptReport.getComponentNum(), acceptReport.getCapacity(), entry.getDistributorId(), entry);
            String settleNumber = map.get("number");//结算方案编号
            BigDecimal fbAmount = new BigDecimal(map.get("fbAmount"));
            logger.info(">>>>>>>>>>>>>>>>>>>>>>>mergeAcceptPass id :{},fbAmount:{}", entry.getId(), fbAmount);
            BigDecimal proportion = accountSetService.findYjsProportion(entry.getDistributorId());
            Record set = accountSetService.findZBJSinglePrice();//质保金设置规则
            String way = set.getStr("way");//结算方式1.按瓦数 2.按组件块数 3.按结算比例（质保金账户使用
            BigDecimal propor = set.getBigDecimal("proportion");
            logger.info("投放款审核通过生成结算明细 proportion:{},propor:{}", proportion, propor);
            BigDecimal zbjSinglePrice = null;
            if (AccountSetConstants.WAY_WS_ONE.equals(way)) {
                zbjSinglePrice = report.getCapacity().multiply(propor);
            } else if (AccountSetConstants.WAY_ZJKS_TWO.equals(way)) {
                zbjSinglePrice = new BigDecimal(report.getComponentNum()).multiply(propor);
            } else if (AccountSetConstants.WAY_JSBL_THREE.equals(way)) {
                zbjSinglePrice = fbAmount.multiply(propor).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }

            logger.info(">>>>>>>>>>>>>>>>>>>>>>>mergeAcceptPass proportion :{},zbjSinglePrice:{}", proportion, zbjSinglePrice);
            BigDecimal fbbwAmount = fbAmount.multiply(new BigDecimal(1)
                            .subtract(proportion.divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP)))
                    .subtract(zbjSinglePrice);
            //生成待结算账户分包并网结算记录
            Operator operator = Operator.of("1", "", "1");
            CrmTraderAccountSettleDetail settleDetail = createSettleDetail(map, entry, fbbwAmount, "1", "0", settleNumber,roofType, entryDesign, projectSetting);
            accountSettleDetailDao.save(settleDetail);
            //生成质保金账户结算记录
            CrmTraderAccountSettleDetail settleDetail2 = createSettleDetail(map, entry, zbjSinglePrice, "3", "1", settleNumber,roofType, entryDesign, projectSetting);
            accountSettleDetailDao.save(settleDetail2);
            //释放授信额上限余额、增加分包款余额、增加验收结算总额、增加质保金总额，增加冻结金额
            CrmTraderAccount account = accountDao.findByTraderId(entry.getDistributorId());
            BigDecimal totalAmount = customerEntryService.getTotalAmount(entry.getId(), "1");
            if (totalAmount != null && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                account.setMaxQuotaAmountBalance(account.getMaxQuotaAmountBalance().add(totalAmount));
            }
            BigDecimal cfAmount = BigDecimal.ZERO;
            //获取惩罚政策 并网天数超过90天（含90天）少于120天（含120天），处罚安装容量*0.05元/W；
            CrmRewardsPunishWay rewardsPunishWay = rewardsPunishWayDao.getRewardsPunishWay("2");
            if (rewardsPunishWay != null) {
                long lowDay = Long.valueOf(rewardsPunishWay.getLowData());
                //获取并网天数
                try {
                    long betweenDay = DateUtils.daysBetween(DateUtils.formatDate(entry.getMaterialFixFinishTime(), "yyyy-MM-dd"), DateUtils.getDate());
                    logger.info("...间隔时间 betweenDay：{}", betweenDay);
                    if (betweenDay >= lowDay) {
                        //超期则生成一条惩罚结算记录
                        cfAmount = report.getCapacity().multiply(new BigDecimal(rewardsPunishWay.getRatioData())).setScale(2, BigDecimal.ROUND_HALF_UP);
                        CrmTraderAccountSettleDetail cfSettleDetail = createSettleCfDetail(map, entry, cfAmount.negate(), "5", "0", rewardsPunishWay.getNumber(), rewardsPunishWay.getRatioData(),roofType, entryDesign, projectSetting);
                        logger.info("..生成第一种惩罚记录金额 cfSettleDetail:{},entryId:{}", cfAmount, entry.getId());
                        accountSettleDetailDao.save(cfSettleDetail);
                    }
                } catch (Exception e) {
                    logger.error("计算并网天数失败 e:", e);
                    throw new BusinessException("计算并网天数失败！");
                }
            }
            BigDecimal cfAmount2 = BigDecimal.ZERO;
            BigDecimal zbjCfAmount = BigDecimal.ZERO;
            //获取惩罚政策 单户装机容量≤10千瓦，基础结算价格每瓦减少0.15元  结算节点：安装验收、并网验收
            CrmRewardsPunishWay rewardsPunishWay3 = rewardsPunishWayDao.getRewardsPunishWay("3");
            if (rewardsPunishWay3 != null) {
                BigDecimal cap = new BigDecimal(String.valueOf(report.getCapacity())).divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_FLOOR); //运算后不要四舍五入
                logger.info("...单户装机容量 cap：{}", cap);
                if (cap.compareTo(new BigDecimal(rewardsPunishWay3.getHighData())) <= 0) {
                    BigDecimal totalAmountCf = report.getCapacity().multiply(new BigDecimal(rewardsPunishWay3.getRatioData())); //总的惩罚金额
                    //生成一条惩罚结算记录
                    logger.info("投放款审核通过生成惩罚金额 proportion:{},propor:{}", proportion, propor);
                    cfAmount2 = totalAmountCf.multiply(new BigDecimal("100").subtract(proportion.add(propor))).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                    CrmTraderAccountSettleDetail cfSettleDetail2 = createSettleCfDetail(map, entry, cfAmount2.negate(), "5", "0", rewardsPunishWay3.getNumber(), rewardsPunishWay3.getRatioData(),roofType,entryDesign,projectSetting);
                    logger.info("..生成第二种惩罚记录结算账户金额 totalAmountCf:{} cfAmount2:{},entryId:{}", totalAmountCf, cfAmount2, entry.getId());
                    accountSettleDetailDao.save(cfSettleDetail2);
                    //生成质保金的惩罚金额  总的惩罚金额 -第一次 +第二次 惩罚的金额
                    //获取第一次生成的惩罚金额
                    BigDecimal oneCfAmount = report.getCapacity().multiply(new BigDecimal(rewardsPunishWay3.getRatioData())).multiply(proportion).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                    zbjCfAmount = totalAmountCf.subtract(oneCfAmount).subtract(cfAmount2);
                    logger.info("..生成质保金惩罚记录金额 zbjCfAmount:{},oneCfAmount:{}", zbjCfAmount, oneCfAmount);
                    CrmTraderAccountSettleDetail cfSettleDetailZbj = createSettleCfDetail(map, entry, zbjCfAmount.negate(), "5", "1", rewardsPunishWay3.getNumber(), rewardsPunishWay3.getRatioData(),roofType,entryDesign,projectSetting);
                    accountSettleDetailDao.save(cfSettleDetailZbj);
                }
            }

            account.setSettleAmount(account.getSettleAmount().add(fbbwAmount).subtract(cfAmount).subtract(cfAmount2));
            account.setSettleRewardsPunishAmount(account.getSettleRewardsPunishAmount().subtract(cfAmount).subtract(cfAmount2));
            account.setSettleAmountYsjs(account.getSettleAmountYsjs().add(fbbwAmount));
            account.setQaAmount(account.getQaAmount().add(zbjSinglePrice).subtract(zbjCfAmount));
            account.setQaAmountFreeze(account.getQaAmountFreeze().add(zbjSinglePrice).subtract(zbjCfAmount));
            accountDao.save(account);
        }
    }


    public CrmTraderAccountSettleDetail createSettleDetail(Map<String ,String> map, CustomerEntry entry, BigDecimal yjsAmount, String type, String objType, String settleNumber, String roofType, CrmCustomerEntryDesign entryDesign, CrmProjectSetting projectSetting) {
        CrmTraderAccountSettleDetail settleDetail = new CrmTraderAccountSettleDetail();
        settleDetail.setEntryId(entry.getId());
        settleDetail.setPowerStationCode(entry.getPowerStationCode());
        settleDetail.setTraderId(entry.getDistributorId());
        settleDetail.setTraderName(entry.getTraderName());
        //0.待结算账户
        settleDetail.setObjType(objType);
        //0.预结算 1.分包并网结算 2.电站整改(减) 3.质保金
        settleDetail.setType(type);
        settleDetail.setAmount(yjsAmount);
        settleDetail.setRoofType(roofType);
        settleDetail.setSchemeType(entry.getSchemeType());
        settleDetail.setSchemeTypeId(entryDesign.getSchemeId());
        settleDetail.setSchemeTypeName(entryDesign.getSchemeName());
        settleDetail.setTenantName(entry.getTenantName());
        settleDetail.setMobile(entry.getMobile());
        settleDetail.setProjectCode(projectSetting.getCode());
        settleDetail.setProjectName(projectSetting.getName());
        settleDetail.setCreateBy("1");
        settleDetail.setCreateTime(new Date());
        settleDetail.setNumber("JS"+ PlantformUtils.getOrderNumber());
        settleDetail.setUnitPrice(new BigDecimal(map.get("amount")));// 结算单价
        settleDetail.setCapacity(new BigDecimal(map.get("actual_capacity")));//
        if ("3".equals(type)) {
            //请款标记:0.可请款 1.冻结
            settleDetail.setFlag("1");
            //质保金到期时间
            settleDetail.setEndTime(DateUtils.yearSub(settleDetail.getCreateTime(),1));
        }
        settleDetail.setSettleNumber(settleNumber);
        return settleDetail;
    }

    public CrmTraderAccountSettleDetail createSettleCfDetail(Map<String ,String> map,CustomerEntry entry, BigDecimal yjsAmount, String type, String objType,String settleNumber,String number, String roofType, CrmCustomerEntryDesign entryDesign, CrmProjectSetting projectSetting) {
        CrmTraderAccountSettleDetail settleDetail = new CrmTraderAccountSettleDetail();
        settleDetail.setEntryId(entry.getId());
        settleDetail.setPowerStationCode(entry.getPowerStationCode());
        settleDetail.setTraderId(entry.getDistributorId());
        settleDetail.setTraderName(entry.getTraderName());
        //0.待结算账户
        settleDetail.setObjType(objType);
        //0.预结算 1.分包并网结算 2.电站整改(减) 3.质保金
        settleDetail.setType(type);
        settleDetail.setAmount(yjsAmount);
        settleDetail.setRoofType(roofType);
        settleDetail.setSchemeType(entry.getSchemeType());
        settleDetail.setSchemeTypeId(entryDesign.getSchemeId());
        settleDetail.setSchemeTypeName(entryDesign.getSchemeName());
        settleDetail.setTenantName(entry.getTenantName());
        settleDetail.setMobile(entry.getMobile());
        settleDetail.setProjectCode(projectSetting.getCode());
        settleDetail.setProjectName(projectSetting.getName());
        settleDetail.setCreateBy("1");
        settleDetail.setCreateTime(new Date());
        settleDetail.setNumber("JS"+PlantformUtils.getOrderNumber());
        settleDetail.setUnitPrice(new BigDecimal(number));// 结算单价
        settleDetail.setCapacity(new BigDecimal(map.get("actual_capacity")));//
        if ("3".equals(type)) {
            //请款标记:0.可请款 1.冻结
            settleDetail.setFlag("1");
            //质保金到期时间
            settleDetail.setEndTime(DateUtils.yearSub(settleDetail.getCreateTime(),1));
        }
        settleDetail.setSettleNumber(settleNumber);
        return settleDetail;
    }

}
