package org.qinan.safetyeval.infrastructure.gatewayimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.qinan.safetyeval.domain.change.model.*;
import org.qinan.safetyeval.domain.entity.QualFilingChangeEntity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.gateway.QualFilingChangeGateway;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.query.QualFilingChangeQuery;
import org.qinan.safetyeval.infrastructure.convertor.*;
import org.qinan.safetyeval.infrastructure.dataobject.OrgPersonnelCertDO;
import org.qinan.safetyeval.infrastructure.dataobject.QualFilingChangeDO;
import org.qinan.safetyeval.infrastructure.mapper.OrgPersonnelCertMapper;
import org.qinan.safetyeval.infrastructure.mapper.QualFilingChangeMapper;
import org.qinan.safetyeval.infrastructure.persistence.domainobject.*;
import org.qinan.safetyeval.infrastructure.persistence.mapper.*;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 备案变更Gateway实现（Infrastructure层）
 *
 * @author safety-eval
 */
@Component
public class QualFilingChangeGatewayImpl implements QualFilingChangeGateway {

    @Resource
    private QualFilingChangeMapper qualFilingChangeMapper;
    @Resource
    private QualFilingCommitmentChangeMapper qualFilingCommitmentChangeMapper;
    @Resource
    private QualFilingEquipmentChangeMapper qualFilingEquipmentChangeMapper;
    @Resource
    private QualFilingMaterialChangeMapper qualFilingMaterialChangeMapper;
    @Resource
    private QualFilingPersonnelChangeMapper qualFilingPersonnelChangeMapper;
    @Resource
    private QualFilingPersonnelCertChangeMapper qualFilingPersonnelCertChangeMapper;
    @Resource
    private OrgPersonnelCertMapper orgPersonnelCertMapper;
    @Resource
    private QualFilingChangeDoConvertor qualFilingChangeDoConvertor;
    @Resource
    private QualFilingCommitmentChangeDoConvertor qualFilingCommitmentChangeDoConvertor;
    @Resource
    private QualFilingEquipmentChangeDoConvertor qualFilingEquipmentChangeDoConvertor;
    @Resource
    private QualFilingMaterialChangeDoConvertor qualFilingMaterialChangeDoConvertor;
    @Resource
    private QualFilingPersonnelChangeDoConvertor qualFilingPersonnelChangeDoConvertor;
    @Resource
    private QualFilingPersonnelCertChangeDoConvertor qualFilingPersonnelCertChangeDoConvertor;

    @Override
    public QualFilingChangeEntity save(QualFilingChangeEntity entity) {
        QualFilingChangeDO dataObject = toDO(entity);
        InsertFieldDefaults.apply(dataObject);
        qualFilingChangeMapper.insert(dataObject);
        entity.setId(dataObject.getId());
        return entity;
    }

    @Override
    public QualFilingChangeEntity get(Long id) {
        QualFilingChangeDO dataObject = qualFilingChangeMapper.selectById(id);
        return toEntity(dataObject);
    }

    @Override
    public List<QualFilingChangeEntity> listByFilingId(Long filingId) {
        LambdaQueryWrapper<QualFilingChangeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QualFilingChangeDO::getFilingId, filingId);
        wrapper.eq(QualFilingChangeDO::getDeleteEnum, "false");
        List<QualFilingChangeDO> dataObjects = qualFilingChangeMapper.selectList(wrapper);
        return dataObjects.stream().map(this::toEntity).collect(Collectors.toList());
    }

    @Override
    public int countByFilingIdAndStatusNot(Long filingId, Integer excludeStatusCode) {
        LambdaQueryWrapper<QualFilingChangeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QualFilingChangeDO::getFilingId, filingId);
        wrapper.ne(QualFilingChangeDO::getFilingStatusCode, excludeStatusCode);
        return qualFilingChangeMapper.selectCount(wrapper).intValue();
    }

    @Override
    public QualFilingChangeEntity modify(QualFilingChangeEntity entity) {
        QualFilingChangeDO dataObject = toDO(entity);
        dataObject.setId(entity.getId());
        InsertFieldDefaults.applyForUpdate(dataObject);
        qualFilingChangeMapper.updateById(dataObject);
        return get(entity.getId());
    }

    @Override
    public void delete(Long id) {
        qualFilingChangeMapper.deleteById(id);
    }

    @Override
    public PageResult<QualFilingChangeEntity> page(QualFilingChangeQuery query) {
        LambdaQueryWrapper<QualFilingChangeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QualFilingChangeDO::getDeleteEnum, "false");
        if (query.getOrgId() != null) {
            wrapper.eq(QualFilingChangeDO::getOrgId, query.getOrgId());
        }
        if (query.getFilingId() != null) {
            wrapper.eq(QualFilingChangeDO::getFilingId, query.getFilingId());
        }
        if (StringUtils.hasText(query.getFilingNo())) {
            wrapper.eq(QualFilingChangeDO::getFilingNo, query.getFilingNo());
        }
        if (query.getFilingStatusCode() != null) {
            wrapper.eq(QualFilingChangeDO::getFilingStatusCode, query.getFilingStatusCode());
        }

        Page<QualFilingChangeDO> page = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<QualFilingChangeDO> result = qualFilingChangeMapper.selectPage(page, wrapper);

        List<QualFilingChangeEntity> entities = result.getRecords().stream()
                .map(this::toEntity)
                .collect(Collectors.toList());

        return PageResult.of(entities, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long aggregationSaveOrEdit(QualFilingChangeEntity entity, QualFilingCommitmentChangeE commitmentEntity
            , List<QualFilingEquipmentChangeE> equipmentEntities, List<QualFilingMaterialChangeE> materialEntities
            , List<QualFilingPersonnelChangeE> personnelEntities, List<QualFilingPersonnelCertChangeE> personnelCertEntities, boolean add) {
        //保存基础信息
        QualFilingChangeDO dataObject = qualFilingChangeDoConvertor.convertEeToDo(entity);
        if (Objects.nonNull(dataObject.getId())) {
            // 编辑
            InsertFieldDefaults.applyForUpdate(dataObject);
            qualFilingChangeMapper.updateById(dataObject);
        } else {
            InsertFieldDefaults.apply(dataObject);
            qualFilingChangeMapper.insert(dataObject);
        }
        if (Objects.isNull(dataObject.getId())) {
            throw new BizException(ErrorCode.QUAL_FILING_CHANGE_NOT_FOUND);
        }

        qualFilingCommitmentChangeMapper.delete(new LambdaQueryWrapper<QualFilingCommitmentChangeDO>()
                .eq(QualFilingCommitmentChangeDO::getFilingChangeId, dataObject.getId()));
        qualFilingMaterialChangeMapper.delete(new LambdaQueryWrapper<QualFilingMaterialChangeDO>()
                .eq(QualFilingMaterialChangeDO::getFilingChangeId, dataObject.getId()));
        qualFilingEquipmentChangeMapper.delete(new LambdaQueryWrapper<QualFilingEquipmentChangeDO>()
                .eq(QualFilingEquipmentChangeDO::getFilingChangeId, dataObject.getId()));

        qualFilingPersonnelCertChangeMapper.delete(new LambdaQueryWrapper<QualFilingPersonnelCertChangeDO>()
                .eq(QualFilingPersonnelCertChangeDO::getFilingChangeId, dataObject.getId()));
        qualFilingPersonnelChangeMapper.delete(new LambdaQueryWrapper<QualFilingPersonnelChangeDO>()
                .eq(QualFilingPersonnelChangeDO::getFilingChangeId, dataObject.getId()));


        //备案承诺书
        QualFilingCommitmentChangeDO commitmentDataObject = qualFilingCommitmentChangeDoConvertor.convertEeToDo(commitmentEntity);
        InsertFieldDefaults.apply(commitmentDataObject);
        commitmentDataObject.setFilingChangeId(dataObject.getId());
        qualFilingCommitmentChangeMapper.insert(commitmentDataObject);
        //备案装备
        equipmentEntities.stream().map(item -> {
            QualFilingEquipmentChangeDO equipmentDataObject = qualFilingEquipmentChangeDoConvertor.convertEeToDo(item);
            InsertFieldDefaults.apply(equipmentDataObject);
            equipmentDataObject.setFilingChangeId(dataObject.getId());
            return equipmentDataObject;
        }).collect(Collectors.toList()).forEach(
                equipmentDataObject -> qualFilingEquipmentChangeMapper.insert(equipmentDataObject));
        //备案材料
        materialEntities.stream().map(item -> {
            QualFilingMaterialChangeDO materialDataObject = qualFilingMaterialChangeDoConvertor.convertEeToDo(item);
            InsertFieldDefaults.apply(materialDataObject);
            materialDataObject.setFilingChangeId(dataObject.getId());
            return materialDataObject;
        }).collect(Collectors.toList()).forEach(
                materialDataObject -> qualFilingMaterialChangeMapper.insert(materialDataObject));
        //备案人员
        personnelEntities.stream().map(item -> {
            QualFilingPersonnelChangeDO personnelDataObject = qualFilingPersonnelChangeDoConvertor.convertEeToDo(item);
            InsertFieldDefaults.apply(personnelDataObject);
            personnelDataObject.setFilingChangeId(dataObject.getId());
            return personnelDataObject;
        }).collect(Collectors.toList()).forEach(
                personnelDataObject -> qualFilingPersonnelChangeMapper.insert(personnelDataObject));
        //备案人员证书
        if (CollectionUtils.isEmpty(personnelCertEntities)) {
            List<Long> sourcePersonnelIds = personnelEntities
                    .stream().map(QualFilingPersonnelChangeE::getSourcePersonnelId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(sourcePersonnelIds)) {
                List<OrgPersonnelCertDO> orgPersonnelCertDOS = orgPersonnelCertMapper.selectList(new LambdaQueryWrapper<OrgPersonnelCertDO>()
                        .in(OrgPersonnelCertDO::getPersonnelId, sourcePersonnelIds));
                if (!CollectionUtils.isEmpty(orgPersonnelCertDOS)) {
                    for (OrgPersonnelCertDO orgPersonnelCertDO : orgPersonnelCertDOS) {
                        QualFilingPersonnelCertChangeDO qualFilingPersonnelCertChangeDO =
                                qualFilingPersonnelCertChangeDoConvertor.convertOrgDoToChangeDo(orgPersonnelCertDO);
                        InsertFieldDefaults.apply(qualFilingPersonnelCertChangeDO);
                        qualFilingPersonnelCertChangeDO.setFilingChangeId(dataObject.getId());
                        qualFilingPersonnelCertChangeMapper.insert(qualFilingPersonnelCertChangeDO);
                    }
                }
            }
        } else {
            personnelCertEntities.stream().map(item -> {
                QualFilingPersonnelCertChangeDO personnelCertDataObject = qualFilingPersonnelCertChangeDoConvertor.convertEeToDo(item);
                InsertFieldDefaults.apply(personnelCertDataObject);
                personnelCertDataObject.setFilingChangeId(dataObject.getId());
                return personnelCertDataObject;
            }).collect(Collectors.toList()).forEach(
                    personnelCertDataObject -> qualFilingPersonnelCertChangeMapper.insert(personnelCertDataObject));
        }
        return dataObject.getId();
    }

    private QualFilingChangeDO toDO(QualFilingChangeEntity entity) {
        QualFilingChangeDO dataObject = new QualFilingChangeDO();
        dataObject.setFilingId(entity.getFilingId());
        dataObject.setChangeFilingId(entity.getChangeFilingId());
        dataObject.setRejectReason(entity.getRejectReason());
        dataObject.setFilingReviewId(entity.getFilingReviewId());
        dataObject.setSubmitTime(entity.getSubmitTime());
        dataObject.setFilingTerritoryCode(entity.getFilingTerritoryCode());
        dataObject.setFilingTerritoryName(entity.getFilingTerritoryName());
        dataObject.setFilingUnitName(entity.getFilingUnitName());
        dataObject.setFilingUnitTypeCode(entity.getFilingUnitTypeCode());
        dataObject.setFilingUnitTypeName(entity.getFilingUnitTypeName());
        dataObject.setFilingNo(entity.getFilingNo());
        dataObject.setBusinessScope(entity.getBusinessScope());
        dataObject.setRegisterAddress(entity.getRegisterAddress());
        dataObject.setOfficeAddress(entity.getOfficeAddress());
        dataObject.setCreditCode(entity.getCreditCode());
        dataObject.setQualCertNo(entity.getQualCertNo());
        dataObject.setLegalPersonPhone(entity.getLegalPersonPhone());
        dataObject.setContactPhone(entity.getContactPhone());
        dataObject.setInfoDisclosureUrl(entity.getInfoDisclosureUrl());
        dataObject.setFixedAssetAmount(entity.getFixedAssetAmount());
        dataObject.setArchiveRoomArea(entity.getArchiveRoomArea());
        dataObject.setFulltimeEvaluatorCount(entity.getFulltimeEvaluatorCount());
        dataObject.setRegisteredEngineerCount(entity.getRegisteredEngineerCount());
        dataObject.setWorkplaceArea(entity.getWorkplaceArea());
        dataObject.setUnitIntro(entity.getUnitIntro());
        dataObject.setAttachmentUrl(entity.getAttachmentUrl());
        dataObject.setFilingStatusCode(entity.getFilingStatusCode());
        dataObject.setFilingStatusName(entity.getFilingStatusName());
        dataObject.setTenantId(entity.getTenantId());
        return dataObject;
    }

    private QualFilingChangeEntity toEntity(QualFilingChangeDO dataObject) {
        if (dataObject == null) {
            return null;
        }
        QualFilingChangeEntity entity = new QualFilingChangeEntity();
        entity.setId(dataObject.getId());
        entity.setFilingId(dataObject.getFilingId());
        entity.setChangeFilingId(dataObject.getChangeFilingId());
        entity.setRejectReason(dataObject.getRejectReason());
        entity.setFilingReviewId(dataObject.getFilingReviewId());
        entity.setSubmitTime(dataObject.getSubmitTime());
        entity.setFilingTerritoryCode(dataObject.getFilingTerritoryCode());
        entity.setFilingTerritoryName(dataObject.getFilingTerritoryName());
        entity.setFilingUnitName(dataObject.getFilingUnitName());
        entity.setFilingUnitTypeCode(dataObject.getFilingUnitTypeCode());
        entity.setFilingUnitTypeName(dataObject.getFilingUnitTypeName());
        entity.setFilingNo(dataObject.getFilingNo());
        entity.setBusinessScope(dataObject.getBusinessScope());
        entity.setRegisterAddress(dataObject.getRegisterAddress());
        entity.setOfficeAddress(dataObject.getOfficeAddress());
        entity.setCreditCode(dataObject.getCreditCode());
        entity.setQualCertNo(dataObject.getQualCertNo());
        entity.setLegalPersonPhone(dataObject.getLegalPersonPhone());
        entity.setContactPhone(dataObject.getContactPhone());
        entity.setInfoDisclosureUrl(dataObject.getInfoDisclosureUrl());
        entity.setFixedAssetAmount(dataObject.getFixedAssetAmount());
        entity.setArchiveRoomArea(dataObject.getArchiveRoomArea());
        entity.setFulltimeEvaluatorCount(dataObject.getFulltimeEvaluatorCount());
        entity.setRegisteredEngineerCount(dataObject.getRegisteredEngineerCount());
        entity.setWorkplaceArea(dataObject.getWorkplaceArea());
        entity.setUnitIntro(dataObject.getUnitIntro());
        entity.setAttachmentUrl(dataObject.getAttachmentUrl());
        entity.setFilingStatusCode(dataObject.getFilingStatusCode());
        entity.setFilingStatusName(dataObject.getFilingStatusName());
        entity.setTenantId(dataObject.getTenantId());
        return entity;
    }
}
