package com.yeejoin.amos.boot.module.jg.biz.edit.process.biz;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.module.jg.api.dto.BizRelationDataDto;
import com.yeejoin.amos.boot.module.jg.api.dto.FieldChangeMeta;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipDataProcessStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.controller.BizDataChangeController;
import com.yeejoin.amos.boot.module.jg.biz.edit.core.IEventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.edit.event.BaseBizDataChangeEvent;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.biz.strategy.IBizDataChangeHandleStrategy;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.equip.CommonEquipDataProcessService;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.equip.strategy.IEquipChangeDataProcessStrategy;
import com.yeejoin.amos.boot.module.jg.biz.service.impl.JgBizChangeLogServiceImpl;
import org.springframework.context.ApplicationContext;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public abstract class DefaultBizDataChangeHandler<U extends BaseBizDataChangeEvent> implements IBizDataChangeHandleStrategy {

    private final IEventPublisher<BaseBizDataChangeEvent> eventPublisher;
    private final ApplicationContext applicationContext;

    protected DefaultBizDataChangeHandler(IEventPublisher<BaseBizDataChangeEvent> eventPublisher, ApplicationContext applicationContext) {
        this.eventPublisher = eventPublisher;
        this.applicationContext = applicationContext;
    }


    @Override
    public final void doSave(String bizId, String applyNo, ModelType model, Map<String, Object> changeData, ReginParams selectedOrgInfo) {
        if (beforeCheck(bizId, applyNo, model, changeData)) {
            JSONObject oData = new JSONObject();
            BeanUtil.copyProperties(changeData, oData);
            // 删除原始提交的变更说明及附件放置后续存放到json
            changeData.remove("changeReason");
            changeData.remove("changeAttachment");
            IEquipChangeDataProcessStrategy dataProcessor = EquipDataProcessStrategyContext.getStrategy(model);
            List<FieldChangeMeta> allChangeColumns = dataProcessor.handle(changeData, bizId);
            List<FieldChangeMeta> bizEditColumns = updBizData(bizId, applyNo, model, changeData);
            allChangeColumns.addAll(bizEditColumns);
            if (bizIsFinished(applyNo, model, changeData)) {
                List<FieldChangeMeta> equipColumns = updCertDataIfBizFin(bizId, applyNo, model, changeData);
                allChangeColumns.addAll(equipColumns);
            }
            // 发送数据变更消息
            publish2OtherBiz(allChangeColumns, applyNo, oData, selectedOrgInfo);
        }
    }

    private void publish2OtherBiz(List<FieldChangeMeta> allChangeColumns, String applyNo, JSONObject oData, ReginParams selectedOrgInfo) {
        if (!allChangeColumns.isEmpty()) {
            BizRelationDataDto bizRelationDataDto = new BizRelationDataDto();
            bizRelationDataDto.setBizId(applyNo);
            bizRelationDataDto.setBizType(canHandleBizType());
            bizRelationDataDto.setRecords(getEqs(applyNo));
            bizRelationDataDto.setChangeReason(oData.getString("changeReason"));
            bizRelationDataDto.setChangeAttachment(JSONObject.toJSONString(oData.get("changeAttachment")));
            bizRelationDataDto.setProjectContraptionIds(getProjectContraptionIds(applyNo));
            bizRelationDataDto.setRecUserName(selectedOrgInfo.getUserModel().getUserName());
            bizRelationDataDto.setUnitCode(selectedOrgInfo.getCompany().getCompanyCode());
            bizRelationDataDto.setUnitName(selectedOrgInfo.getCompany().getCompanyName());
            eventPublisher.publish(new BaseBizDataChangeEvent(this, bizRelationDataDto, allChangeColumns, RequestContext.cloneRequestContext()));
        }
    }

    @Override
    public IPage<?> getDetail(String applyNo, BizDataChangeController.DetailType type, JSONObject searchParams) {
        CommonEquipDataProcessService service = applicationContext.getBean(CommonEquipDataProcessService.class);
        switch (type) {
            case equip:
                return service.getEquListByRecords(getEqs(applyNo), searchParams);
            case project:
                return service.getProjectContraptionsBySeqs(getProjectContraptionIds(applyNo), searchParams);
            default:
                throw new BadRequest("unknown type for getDetail");
        }
    }

    @Override
    public Map<String, ?> getSubDetail(String applyNo, String bizId, BizDataChangeController.DetailType type) {
        CommonEquipDataProcessService service = applicationContext.getBean(CommonEquipDataProcessService.class);
        switch (type) {
            case equip:
                return service.getEquipDetailByRecord(bizId);
            case project:
                return service.getProjectContraptionBySeq(bizId, getEqs(applyNo));
            default:
                throw new BadRequest("unknown type for getSubDetail");
        }
    }

    @Override
    public IPage<?> getChangeLogs(String bizId, int current, int size) {
        Set<String> changeIds = new HashSet<>();
        changeIds.addAll(getEqs(bizId));
        changeIds.addAll(getProjectContraptionIds(bizId));
        JgBizChangeLogServiceImpl service = applicationContext.getBean(JgBizChangeLogServiceImpl.class);
        return service.queryPageListByChangeIds(changeIds, current, size);
    }
}
