package org.qinan.safetyeval.app.executor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.qinan.safetyeval.app.orchestrator.QualFilingOrchestrator;
import org.qinan.safetyeval.client.api.QualFilingApi;
import org.qinan.safetyeval.client.change.request.QualFilingCommitmentChangeAddCmd;
import org.qinan.safetyeval.client.change.request.QualFilingEquipmentChangeAddCmd;
import org.qinan.safetyeval.client.change.request.QualFilingMaterialChangeAddCmd;
import org.qinan.safetyeval.client.change.request.QualFilingPersonnelChangeAddCmd;
import org.qinan.safetyeval.client.co.QualFilingCO;
import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO;
import org.qinan.safetyeval.client.co.QualFilingDetailCO;
import org.qinan.safetyeval.client.dto.*;
import org.qinan.safetyeval.domain.constant.QualFilingApplyTypeEnum;
import org.qinan.safetyeval.domain.constant.QualFilingReviewResultEnum;
import org.qinan.safetyeval.domain.entity.*;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.service.QualFilingDomainService;
import org.qinan.safetyeval.infrastructure.dataobject.*;
import org.qinan.safetyeval.infrastructure.mapper.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * 资质备案申请执行器（App层）
 */
@Service
public class QualFilingExecutor implements QualFilingApi {

    @Lazy
    @Autowired(required = false)
    private QualFilingDomainService qualFilingDomainService;

    @Resource
    private QualFilingOrchestrator qualFilingOrchestrator;

    @Resource
    private QualFilingChangeExecutor qualFilingChangeExecutor;

    @Resource
    private QualFilingMapper qualFilingMapper;
    @Resource
    private QualFilingCommitmentMapper qualFilingCommitmentMapper;
    @Resource
    private QualFilingEquipmentMapper qualFilingEquipmentMapper;
    @Resource
    private QualFilingMaterialMapper qualFilingMaterialMapper;
    @Resource
    private QualFilingPersonnelMapper qualFilingPersonnelMapper;
    @Resource
    private QualFilingPersonnelCertMapper qualFilingPersonnelCertMapper;

    @Override
    public SingleResponse<QualFilingCO> add(QualFilingAddCmd cmd) {
        QualFilingEntity entity = new QualFilingEntity();
        entity.setFilingTerritoryCode(cmd.getFilingTerritoryCode());
        entity.setFilingTerritoryName(cmd.getFilingTerritoryName());
        entity.setFilingUnitName(cmd.getFilingUnitName());
        entity.setFilingUnitTypeCode(cmd.getFilingUnitTypeCode());
        entity.setFilingUnitTypeName(cmd.getFilingUnitTypeName());
        entity.setFilingNo(cmd.getFilingNo());
        entity.setBusinessScope(cmd.getBusinessScope());
        entity.setRegisterAddress(cmd.getRegisterAddress());
        entity.setOfficeAddress(cmd.getOfficeAddress());
        entity.setCreditCode(cmd.getCreditCode());
        entity.setQualCertNo(cmd.getQualCertNo());
        entity.setLegalPersonPhone(cmd.getLegalPersonPhone());
        entity.setContactPhone(cmd.getContactPhone());
        entity.setInfoDisclosureUrl(cmd.getInfoDisclosureUrl());
        entity.setFixedAssetAmount(cmd.getFixedAssetAmount());
        entity.setArchiveRoomArea(cmd.getArchiveRoomArea());
        entity.setFulltimeEvaluatorCount(cmd.getFulltimeEvaluatorCount());
        entity.setRegisteredEngineerCount(cmd.getRegisteredEngineerCount());
        entity.setWorkplaceArea(cmd.getWorkplaceArea());
        entity.setUnitIntro(cmd.getUnitIntro());
        entity.setAttachmentUrl(cmd.getAttachmentUrl());
        entity.setFilingStatusCode(cmd.getFilingStatusCode());
        entity.setFilingStatusName(cmd.getFilingStatusName());
        entity.setApplyTypeCode(cmd.getApplyTypeCode());
        entity.setApplyTypeName(cmd.getApplyTypeName());
        QualFilingEntity result = qualFilingDomainService.add(entity);
        return SingleResponse.success(toLegacyCO(result));
    }

    @Override
    public SingleResponse<QualFilingCO> get(Long id) {
        QualFilingEntity entity = qualFilingDomainService.get(id);
        return SingleResponse.success(toLegacyCO(entity));
    }

    @Override
    public SingleResponse<QualFilingCO> modify(QualFilingModifyCmd cmd) {
        return saveDraft(cmd);
    }

    @Override
    public SingleResponse<Void> delete(Long id) {
        qualFilingDomainService.delete(id);
        return SingleResponse.success();
    }

    @Override
    public PageResponse<QualFilingCO> page(QualFilingPageQuery query) {
        PageResult<QualFilingCO> pageResult = qualFilingOrchestrator.page(query);
        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal());
    }

    @Override
    public SingleResponse<QualFilingCO> draft(Integer applyTypeCode) {
        return SingleResponse.success(qualFilingOrchestrator.createDraft(applyTypeCode));
    }

    @Override
    public SingleResponse<QualFilingCO> saveDraft(QualFilingModifyCmd cmd) {
        return SingleResponse.success(qualFilingOrchestrator.saveDraft(cmd));
    }

    @Override
    public SingleResponse<QualFilingCO> submit(Long id) {
        return SingleResponse.success(qualFilingOrchestrator.submit(id));
    }

    @Override
    public SingleResponse<QualFilingCO> approve(Long id) {
        return SingleResponse.success(qualFilingOrchestrator.approve(id));
    }

    @Override
    public SingleResponse<QualFilingCO> reject(QualFilingRejectCmd cmd) {
        return SingleResponse.success(qualFilingOrchestrator.reject(cmd.getId(), cmd.getRejectReason()));
    }

    @Override
    public SingleResponse<QualFilingDetailCO> detail(Long id) {
        return SingleResponse.success(qualFilingOrchestrator.getDetail(id));
    }

    @Override
    public SingleResponse<QualFilingCO> filedDraft() {
        return SingleResponse.success(
                qualFilingOrchestrator.createDraft(QualFilingApplyTypeEnum.FILED_MANAGE.getCode()));
    }

    @Override
    public SingleResponse<QualFilingCO> uploadAttachment(QualFilingAttachmentUploadCmd cmd) {
        return SingleResponse.success(qualFilingOrchestrator.uploadMainAttachment(cmd.getId(), cmd.getAttachmentUrl()));
    }

    @Override
    public SingleResponse<List<QualFilingComplianceCheckResultCO>> complianceCheck(Long id) {
        return SingleResponse.success(qualFilingOrchestrator.complianceCheck(id));
    }

    @Override
    public SingleResponse<QualFilingCO> aggregationSaveOrEdit(AggregationSaveOrEditQualFilingCmd cmd) {
        QualFilingCO co = new QualFilingCO();
        BeanUtils.copyProperties(cmd.getQualFilingAddCmd(), co);
        // 拷贝基本信息
        QualFilingEntity entity = new QualFilingEntity();
        BeanUtils.copyProperties(cmd.getQualFilingAddCmd(),entity);
        //备案承诺书
        QualFilingCommitmentEntity commitmentEntity = new QualFilingCommitmentEntity();
        BeanUtils.copyProperties(cmd.getQualFilingCommitmentAddCmd(),commitmentEntity);
        //备案装备
        List<QualFilingEquipmentEntity> equipmentEntities = cmd.getQualFilingEquipmentAddCmds().stream().map(item -> {
            QualFilingEquipmentEntity equipmentEntity = new QualFilingEquipmentEntity();
            BeanUtils.copyProperties(item, equipmentEntity);
            return equipmentEntity;
        }).collect(Collectors.toList());
        //备案材料清单
        List<QualFilingMaterialEntity> materialEntities = cmd.getQualFilingMaterialAddCmds().stream().map(item -> {
            QualFilingMaterialEntity materialEntity = new QualFilingMaterialEntity();
            BeanUtils.copyProperties(item, materialEntity);
            return materialEntity;
        }).collect(Collectors.toList());
        //备案人员
        List<QualFilingPersonnelEntity> personnelEntities = cmd.getQualFilingPersonnelAddCmds().stream().map(item -> {
            QualFilingPersonnelEntity personnelEntity = new QualFilingPersonnelEntity();
            BeanUtils.copyProperties(item, personnelEntity);
            return personnelEntity;
        }).collect(Collectors.toList());
        //备案人员证书列表
        List<QualFilingPersonnelCertEntity> personnelCertEntities = Collections.emptyList();
        if (!CollectionUtils.isEmpty(cmd.getQualFilingPersonnelCertAddCmds())) {
            personnelCertEntities = cmd.getQualFilingPersonnelCertAddCmds().stream().map(item -> {
                QualFilingPersonnelCertEntity personnelCertEntity = new QualFilingPersonnelCertEntity();
                BeanUtils.copyProperties(item, personnelCertEntity);
                return personnelCertEntity;
            }).collect(Collectors.toList());
        }
       Long id =  qualFilingDomainService.aggregationSaveOrEdit(entity, commitmentEntity, equipmentEntities, materialEntities, personnelEntities, personnelCertEntities);
       co.setId(id);
       return SingleResponse.success(co);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void review(QualFilingReviewAddCmd cmd) {
        qualFilingDomainService.review(cmd.getFilingId(), cmd.getReviewResult(), cmd.getReviewResultRemark(), cmd.getFilingExpertId(), cmd.getFilingExpertName(), cmd.getReviewOpinion());
        if (QualFilingReviewResultEnum.PASS.getCode() == Integer.parseInt(cmd.getReviewResult())) {
            // 审核通过,需要新增资质变更记录
            AggregationSaveOrEditQualFilingChangeCmd cmdSync = new AggregationSaveOrEditQualFilingChangeCmd();
            // 基本信息
            QualFilingDO qualFilingDO = qualFilingMapper.selectById(cmd.getFilingId());
            QualFilingChangeAddCmd qualFilingChangeAddCmd = new QualFilingChangeAddCmd();
            BeanUtils.copyProperties(qualFilingDO, qualFilingChangeAddCmd, "id");
            qualFilingChangeAddCmd.setFilingId(qualFilingDO.getId());
            cmdSync.setQualFilingChangeAddCmd(qualFilingChangeAddCmd);
            // 备案承诺书
            QualFilingCommitmentDO qualFilingCommitmentDO = qualFilingCommitmentMapper.selectOne(new LambdaQueryWrapper<QualFilingCommitmentDO>()
                    .eq(QualFilingCommitmentDO::getFilingId, cmd.getFilingId()));
            QualFilingCommitmentChangeAddCmd qualFilingCommitmentChangeAddCmd = new QualFilingCommitmentChangeAddCmd();
            BeanUtils.copyProperties(qualFilingCommitmentDO, qualFilingCommitmentChangeAddCmd);
            cmdSync.setQualFilingCommitmentChangeAddCmd(qualFilingCommitmentChangeAddCmd);
            // 备案装备
            List<QualFilingEquipmentDO> qualFilingEquipmentDOs = qualFilingEquipmentMapper.selectList(new LambdaQueryWrapper<QualFilingEquipmentDO>()
                    .eq(QualFilingEquipmentDO::getFilingId, cmd.getFilingId()));
            cmdSync.setQualFilingEquipmentChangeAddCmds(qualFilingEquipmentDOs.stream().map(item -> {
                QualFilingEquipmentChangeAddCmd qualFilingEquipmentChangeAddCmd = new QualFilingEquipmentChangeAddCmd();
                BeanUtils.copyProperties(item, qualFilingEquipmentChangeAddCmd);
                return qualFilingEquipmentChangeAddCmd;
            }).collect(Collectors.toList()));
            // 备案材料清单
            List<QualFilingMaterialDO> qualFilingMaterialDOs = qualFilingMaterialMapper.selectList(new LambdaQueryWrapper<QualFilingMaterialDO>()
                    .eq(QualFilingMaterialDO::getFilingId, cmd.getFilingId()));
            cmdSync.setQualFilingMaterialChangeAddCmds(qualFilingMaterialDOs.stream().map(item -> {
                QualFilingMaterialChangeAddCmd qualFilingMaterialChangeAddCmd = new QualFilingMaterialChangeAddCmd();
                BeanUtils.copyProperties(item, qualFilingMaterialChangeAddCmd);
                return qualFilingMaterialChangeAddCmd;
            }).collect(Collectors.toList()));
            // 备案人员
            List<QualFilingPersonnelDO> qualFilingPersonnelDOs = qualFilingPersonnelMapper.selectList(new LambdaQueryWrapper<QualFilingPersonnelDO>()
                    .eq(QualFilingPersonnelDO::getFilingId, cmd.getFilingId()));
            cmdSync.setQualFilingPersonnelChangeAddCmds(qualFilingPersonnelDOs.stream().map(item -> {
                QualFilingPersonnelChangeAddCmd qualFilingPersonnelChangeAddCmd = new QualFilingPersonnelChangeAddCmd();
                BeanUtils.copyProperties(item, qualFilingPersonnelChangeAddCmd);
                return qualFilingPersonnelChangeAddCmd;
            }).collect(Collectors.toList()));
            qualFilingChangeExecutor.aggregationSaveOrEdit(cmdSync);
        }
    }

    private QualFilingCO toLegacyCO(QualFilingEntity entity) {
        if (entity == null) {
            return null;
        }
        QualFilingCO co = new QualFilingCO();
        co.setId(entity.getId());
        co.setFilingTerritoryCode(entity.getFilingTerritoryCode());
        co.setFilingTerritoryName(entity.getFilingTerritoryName());
        co.setFilingUnitName(entity.getFilingUnitName());
        co.setFilingUnitTypeCode(entity.getFilingUnitTypeCode());
        co.setFilingUnitTypeName(entity.getFilingUnitTypeName());
        co.setFilingNo(entity.getFilingNo());
        co.setBusinessScope(entity.getBusinessScope());
        co.setRegisterAddress(entity.getRegisterAddress());
        co.setOfficeAddress(entity.getOfficeAddress());
        co.setCreditCode(entity.getCreditCode());
        co.setQualCertNo(entity.getQualCertNo());
        co.setLegalPersonPhone(entity.getLegalPersonPhone());
        co.setContactPhone(entity.getContactPhone());
        co.setInfoDisclosureUrl(entity.getInfoDisclosureUrl());
        co.setFixedAssetAmount(entity.getFixedAssetAmount());
        co.setArchiveRoomArea(entity.getArchiveRoomArea());
        co.setFulltimeEvaluatorCount(entity.getFulltimeEvaluatorCount());
        co.setRegisteredEngineerCount(entity.getRegisteredEngineerCount());
        co.setWorkplaceArea(entity.getWorkplaceArea());
        co.setUnitIntro(entity.getUnitIntro());
        co.setAttachmentUrl(entity.getAttachmentUrl());
        co.setOriginFilingId(entity.getOriginFilingId());
        co.setRejectReason(entity.getRejectReason());
        co.setFilingReviewId(entity.getFilingReviewId());
        co.setSubmitTime(entity.getSubmitTime());
        co.setApproveTime(entity.getApproveTime());
        co.setFilingStatusCode(entity.getFilingStatusCode());
        co.setFilingStatusName(entity.getFilingStatusName());
        co.setApplyTypeCode(entity.getApplyTypeCode());
        co.setApplyTypeName(entity.getApplyTypeName());
        co.setTenantId(entity.getTenantId());
        return co;
    }
}
