package com.clx.performance.service.impl.breakcontract;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clx.order.vo.feign.FeignOrderInfoVO;
import com.clx.performance.dao.breakcontract.BreakContractOwnerRecordDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementOwnerDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementOwnerDetailDao;
import com.clx.performance.enums.*;
import com.clx.performance.extranal.user.OrderService;
import com.clx.performance.extranal.user.OwnerInfoService;
import com.clx.performance.model.breakcontract.BreakContractOwnerRecord;
import com.clx.performance.model.breakcontract.BreakContractSettlementOwner;
import com.clx.performance.model.breakcontract.BreakContractSettlementOwnerDetail;
import com.clx.performance.param.pc.breakcontract.carrier.BreakContractOwnerRecordAddParam;
import com.clx.performance.param.pc.breakcontract.carrier.PageBreakContractOwnerRecordParam;
import com.clx.performance.param.pc.breakcontract.owner.PageOwnerBreakContractOwnerRecordParam;
import com.clx.performance.param.pc.owner.OwnerConfirmBreakContractSettlementParam;
import com.clx.performance.service.SendInternalMessageService;
import com.clx.performance.service.breakcontract.BreakContractOwnerRecordService;
import com.clx.performance.service.breakcontract.BreakContractSettlementLogService;
import com.clx.performance.service.impl.UniqueOrderNumService;
import com.clx.performance.struct.breakcontract.BreakContractOwnerRecordStruct;
import com.clx.performance.struct.breakcontract.BreakContractSettlementOwnerDetailStruct;
import com.clx.performance.struct.breakcontract.BreakContractSettlementOwnerStruct;
import com.clx.performance.vo.pc.breakcontract.carrier.BreakContractOwnerRecordVO;
import com.clx.performance.vo.pc.breakcontract.owner.PageOwnerBreakContractOwnerRecordVO;
import com.clx.user.vo.feign.OwnerInfoFeignVO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.utils.LocalDateTimeUtils;
import com.msl.user.data.UserSessionData;
import com.msl.user.utils.TokenUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author liruixin
 * Date 2023-10-24
 * Time 16:02
 */
@Slf4j
@Service
@AllArgsConstructor
public class BreakContractOwnerRecordServiceImpl  implements BreakContractOwnerRecordService {


    private final BreakContractOwnerRecordDao breakContractOwnerRecordDao;

    private final OrderService orderService;

    private final UniqueOrderNumService uniqueOrderNumService;

    private final OwnerInfoService ownerInfoService;

    private final BreakContractOwnerRecordStruct breakContractOwnerRecordStruct;

    private final BreakContractSettlementOwnerDetailStruct breakContractSettlementOwnerDetailStruct;

    private final BreakContractSettlementOwnerStruct breakContractSettlementOwnerStruct;

    private final BreakContractSettlementOwnerDao breakContractSettlementOwnerDao;

    private final BreakContractSettlementOwnerDetailDao breakContractSettlementOwnerDetailDao;

    private final BreakContractSettlementLogService breakContractSettlementLogService;

    private final SendInternalMessageService sendInternalMessageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRecord(BreakContractOwnerRecordAddParam param) {
        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        Long userNo = loginUserInfo.getUserNo();

        String breakNo = "WYD"+childNoGenerate();

        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(param.getOrderNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        OwnerInfoFeignVO ownerInfo = ownerInfoService.getOwnerInfo(orderInfo.getOwnerUserNo());

        BreakContractOwnerRecord record = new BreakContractOwnerRecord();
        record.setOrderSource(orderInfo.getOrderSource());
        record.setOwnerCompanyNo(orderInfo.getCompanyNo());
        record.setBreakNo(breakNo);
        record.setTriggerType(BreakContractRecordEnum.TriggerType.MANUAL.getCode());
        if (Objects.equals(param.getBreakContractPartyType(), BreakContractRecordEnum.BreakContractPartyType.OWNER.getCode())) {
            record.setBreakContractPartyType(BreakContractRecordEnum.BreakContractPartyType.OWNER.getCode());
        }
        else {
            record.setBreakContractPartyType(BreakContractRecordEnum.BreakContractPartyType.PLATFORM.getCode());
        }

        record.setOrderNo(param.getOrderNo());
        record.setFigure(param.getFigure());
        record.setRemark(param.getRemark());

        record.setOwnerUserNo(ownerInfo.getUserNo());
        record.setOwnerName(ownerInfo.getName());

        record.setCreateBy(userNo);
        record.setCreateName(loginUserInfo.getUserName());

        if(Objects.equals(param.getBreakContractPartyType(), BreakContractRecordEnum.BreakContractPartyType.PLATFORM.getCode())){
            record.setConfirmStatus(BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMED.getCode());
        }else{
            record.setConfirmStatus(BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMING.getCode());
        }
        String settlementNo = "WYJSD"+childNoGenerate();
        record.setSettlementNo(settlementNo);

        //保存违约记录
        breakContractOwnerRecordDao.saveEntity(record);

        //生成违约结算单
        if(Objects.equals(param.getBreakContractPartyType(), BreakContractRecordEnum.BreakContractPartyType.PLATFORM.getCode())){
            generateBreakContractSettlement(record.getId());
        }

        //货主违约通知 站内信
        sendInternalMessageService.sendInternalMessageMq(InternalMessageTemplateEnum.PlatformType.CARRIER.getCode(),
                InternalMessageTemplateEnum.BusinessType.WAIT_APPROVED_ITEM.getCode(),
                InternalMessageTemplateEnum.CUSTOM_OWNER_TRIGGER_BREAK_CONTRACT_CODE, Collections.singletonList(breakNo),null);

    }

    @Override
    public IPage<BreakContractOwnerRecordVO> pageRecord(PageBreakContractOwnerRecordParam param) {
        IPage<BreakContractOwnerRecordVO> vo = breakContractOwnerRecordDao.pageByParam(param);
        List<BreakContractOwnerRecordVO> records = vo.getRecords();
        for(BreakContractOwnerRecordVO recordVO:records){
            if(!Objects.equals(recordVO.getConfirmStatus(),BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMED.getCode())){
                recordVO.setSettlementNo("");
            }
        }
        return vo;
    }

    /**
     * 创建违约号
     */
    private String childNoGenerate() {
        return uniqueOrderNumService.getUniqueOrderNum(
                LocalDateTimeUtils.convertLocalDateTimeToString(LocalDateTime.now(), LocalDateTimeUtils.DATE_DAY));
    }

    @Override
    public IPage<PageOwnerBreakContractOwnerRecordVO> pageOwnerRecord(PageOwnerBreakContractOwnerRecordParam param) {
        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        param.setOwnerUserNo(loginUserInfo.getCompanyNo());
        IPage<BreakContractOwnerRecord> ownerRecord = breakContractOwnerRecordDao.pageOwnerBreakContractOwnerRecordList(param);
        List<PageOwnerBreakContractOwnerRecordVO> ownerRecordVO = breakContractOwnerRecordStruct.covertToOwnerList(ownerRecord.getRecords());
        for(PageOwnerBreakContractOwnerRecordVO recordVO:ownerRecordVO){
            if(!Objects.equals(recordVO.getConfirmStatus(),BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMED.getCode())){
                recordVO.setSettlementNo("");
            }
        }
        return new Page<PageOwnerBreakContractOwnerRecordVO>().setRecords(ownerRecordVO).setTotal(ownerRecord.getTotal()).setPages(ownerRecord.getPages());

    }

    @Override
    public void autoSaveRecord(BreakContractOwnerRecordAddParam param) {

        String breakNo = "WYD"+childNoGenerate();

        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(param.getOrderNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        OwnerInfoFeignVO ownerInfo = ownerInfoService.getOwnerInfo(orderInfo.getOwnerUserNo());

        BreakContractOwnerRecord record = new BreakContractOwnerRecord();
        record.setBreakNo(breakNo);
        record.setOrderSource(orderInfo.getOrderSource());
        record.setOwnerCompanyNo(orderInfo.getCompanyNo());
        record.setTriggerType(BreakContractRecordEnum.TriggerType.SYSTEM.getCode());
        record.setBreakContractPartyType(BreakContractRecordEnum.BreakContractPartyType.OWNER.getCode());

        record.setOrderNo(param.getOrderNo());
        record.setFigure(param.getFigure());
        record.setRemark(param.getRemark());

        record.setOwnerUserNo(ownerInfo.getUserNo());
        record.setOwnerName(ownerInfo.getName());

        record.setCreateBy(0L);
        record.setCreateName("系统");

        record.setConfirmStatus(BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMING.getCode());
        String settlementNo = "WYJSD"+childNoGenerate();
        record.setSettlementNo(settlementNo);
        //保存违约记录
        breakContractOwnerRecordDao.saveEntity(record);

        //货主违约通知 站内信
        sendInternalMessageService.sendInternalMessageMq(InternalMessageTemplateEnum.PlatformType.CARRIER.getCode(),
                InternalMessageTemplateEnum.BusinessType.WAIT_APPROVED_ITEM.getCode(),
                InternalMessageTemplateEnum.CUSTOM_OWNER_TRIGGER_BREAK_CONTRACT_CODE, Collections.singletonList(breakNo),null);

    }


    @Override
    public void updateConfirmStatus(OwnerConfirmBreakContractSettlementParam param) {

        BreakContractOwnerRecord record = breakContractOwnerRecordDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(record.getConfirmStatus(),BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMING.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        //驳回或者确认
        BreakContractOwnerRecord ownerRecord  = new BreakContractOwnerRecord();
        ownerRecord.setId(param.getId());
        ownerRecord.setConfirmStatus(param.getConfirmStatus());
        ownerRecord.setRejectReason(param.getRejectReason());
        breakContractOwnerRecordDao.updateConfirmStatus(ownerRecord);

        //货主同意生成违约结算单
        if(Objects.equals(param.getConfirmStatus(),BreakContractOwnerRecordEnum.ConfirmStatus.CONFIRMED.getCode())){
            generateBreakContractSettlement(param.getId());
        }

    }


    /**
     * 生成违约结算单
     * @param breakContractId
     */
    @Override
    public void generateBreakContractSettlement(Integer breakContractId){
        //违约记录查询
        BreakContractOwnerRecord record = breakContractOwnerRecordDao.getEntityByKey(breakContractId).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        //货主违约计费明细
        BreakContractSettlementOwnerDetail breakOwnerDetail = breakContractSettlementOwnerDetailStruct.convert(record);

        //货主违约结算单
        BreakContractSettlementOwner breakOwner = breakContractSettlementOwnerStruct.convert(breakOwnerDetail);
        breakOwner.setStatus(BreakContractSettlementOwnerEnum.Status.TO_BE_ACCOUNT.getCode());

        //保存违约计费
        breakOwner.setId(null);
        breakOwner.setCreateTime(null);
        breakOwner.setModifiedTime(null);
        breakContractSettlementOwnerDao.saveEntity(breakOwner);

        //保存违约结算单
        breakOwnerDetail.setId(null);
        breakOwnerDetail.setCreateTime(null);
        breakOwnerDetail.setModifiedTime(null);
        breakContractSettlementOwnerDetailDao.saveEntity(breakOwnerDetail);

        //保存结算单日志----创建结算单
        breakContractSettlementLogService.saveBreakSettlementLog(record.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.CREATE_SETTLEMENT.getCode(),BreakContractSettlementLogEnum.Type.CREATE_SETTLEMENT.getMsg(),
                OrderChildLogEnum.CreateType.OWNER.getCode(),record.getCreateBy(),record.getCreateName());
    }

}
