package org.qinan.safetyeval.app.orchestrator;

import org.qinan.safetyeval.app.support.*;
import org.qinan.safetyeval.client.co.*;
import org.qinan.safetyeval.client.dto.QualFilingModifyCmd;
import org.qinan.safetyeval.client.dto.QualFilingPageQuery;
import org.qinan.safetyeval.domain.change.gateway.QualFilingCommitmentChangeGateway;
import org.qinan.safetyeval.domain.change.gateway.QualFilingMaterialChangeGateway;
import org.qinan.safetyeval.domain.change.gateway.QualFilingPersonnelChangeGateway;
import org.qinan.safetyeval.domain.change.model.QualFilingCommitmentChangeE;
import org.qinan.safetyeval.domain.constant.*;
import org.qinan.safetyeval.domain.entity.*;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.gateway.*;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.query.QualFilingQuery;
import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter;
import org.qinan.safetyeval.infrastructure.support.OrgContextResolver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 资质备案业务编排
 */
@Service
public class QualFilingOrchestrator {

    @Resource
    private QualFilingGateway qualFilingGateway;

    @Resource
    private QualFilingMaterialGateway qualFilingMaterialGateway;

    @Resource
    private QualFilingCommitmentGateway qualFilingCommitmentGateway;

    @Resource
    private QualFilingPersonnelGateway qualFilingPersonnelGateway;

    @Resource
    private QualFilingPersonnelCertGateway qualFilingPersonnelCertGateway;

    @Resource
    private QualFilingEquipmentGateway qualFilingEquipmentGateway;

    @Resource
    private QualFilingChangeGateway qualFilingChangeGateway;

    @Resource
    private QualFilingChangeDetailGateway qualFilingChangeDetailGateway;

    @Resource
    private QualFilingPersonnelChangeGateway qualFilingPersonnelChangeGateway;

    @Resource
    private QualFilingCommitmentChangeGateway qualFilingCommitmentChangeGateway;

    @Resource
    private QualFilingMaterialChangeGateway qualFilingMaterialChangeGateway;

    @Resource
    private OrgInfoGateway orgInfoGateway;

    @Resource
    private QualFilingStatusGuard statusGuard;

    @Resource
    private QualFilingMaterialTemplateProvider materialTemplateProvider;

    @Resource
    private QualFilingOrgPersonnelImporter personnelImporter;

    @Resource
    private QualFilingOrgEquipmentImporter equipmentImporter;

    @Resource
    private QualFilingChangeDiffer changeDiffer;

    @Resource
    private QualFilingAttachmentHelper attachmentHelper;

    @Resource
    private OrgContextResolver orgContextResolver;

    @Value("${safety-eval.public-api.tenant-id:0}")
    private Long fallbackTenantId;

    @Transactional
    public QualFilingCO createDraft(Integer applyTypeCode) {
        QualFilingApplyTypeEnum applyType = QualFilingApplyTypeEnum.ofCode(applyTypeCode);
        if (applyType == null) {
            applyType = QualFilingApplyTypeEnum.APPLICATION;
        }
        QualFilingEntity entity = new QualFilingEntity();
        entity.setApplyTypeCode(applyType.getCode());
        entity.setApplyTypeName(applyType.getName());
        entity.setFilingStatusCode(QualFilingStatusEnum.DRAFT.getCode());
        entity.setFilingStatusName(QualFilingStatusEnum.DRAFT.getName());
        entity.setOrgId(resolveOrgId());
        entity.setTenantId(resolveTenantId());
        prefillFromOrgInfo(entity);
        QualFilingEntity saved = qualFilingGateway.save(entity);
        return toCO(saved);
    }

    @Transactional
    public QualFilingCO saveDraft(QualFilingModifyCmd cmd) {
        QualFilingEntity existing = qualFilingGateway.get(cmd.getId());
        statusGuard.ensureEditable(existing);
        applyModifyFields(existing, cmd);
        markDraftSaved(existing);
        QualFilingEntity saved = qualFilingGateway.modify(existing);
        return toCO(saved);
    }

    /**
     * 用户点击暂存：暂存保持；已打回保持原状态
     */
    private void markDraftSaved(QualFilingEntity filing) {
        Integer code = filing.getFilingStatusCode();
        if (code == null || code == QualFilingStatusEnum.DRAFT.getCode()) {
            filing.setFilingStatusCode(QualFilingStatusEnum.DRAFT.getCode());
            filing.setFilingStatusName(QualFilingStatusEnum.DRAFT.getName());
        }
    }

    @Transactional
    public QualFilingCO submit(Long id) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        statusGuard.ensureSubmittable(filing);
        validateBeforeSubmit(filing);
        filing.setFilingStatusCode(QualFilingStatusEnum.REVIEWING.getCode());
        filing.setFilingStatusName(QualFilingStatusEnum.REVIEWING.getName());
        filing.setSubmitTime(LocalDateTime.now());
        QualFilingEntity saved = qualFilingGateway.modify(filing);
        return toCO(saved);
    }

    @Transactional
    public QualFilingCO approve(Long id) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        if (filing == null || filing.getFilingStatusCode() == null
                || filing.getFilingStatusCode() != QualFilingStatusEnum.REVIEWING.getCode()) {
            throw new BizException(ErrorCode.QUAL_FILING_STATUS_INVALID);
        }
        filing.setFilingStatusCode(QualFilingStatusEnum.FILED.getCode());
        filing.setFilingStatusName(QualFilingStatusEnum.FILED.getName());
        filing.setApproveTime(LocalDateTime.now());
        QualFilingEntity saved = qualFilingGateway.modify(filing);
        if (QualFilingApplyTypeEnum.APPLICATION.getCode() == saved.getApplyTypeCode()) {
            createFiledManageRecord(saved);
        }
        return toCO(saved);
    }

    @Transactional
    public QualFilingCO reject(Long id, String rejectReason) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        if (filing == null || filing.getFilingStatusCode() == null
                || filing.getFilingStatusCode() != QualFilingStatusEnum.REVIEWING.getCode()) {
            throw new BizException(ErrorCode.QUAL_FILING_STATUS_INVALID);
        }
        filing.setFilingStatusCode(QualFilingStatusEnum.REJECTED.getCode());
        filing.setFilingStatusName(QualFilingStatusEnum.REJECTED.getName());
        filing.setRejectReason(rejectReason);
        return toCO(qualFilingGateway.modify(filing));
    }

    public QualFilingDetailCO getDetail(Long id) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        if (filing == null) {
            throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
        }
        QualFilingDetailCO detail = new QualFilingDetailCO();
        BeanUtils.copyProperties(toCO(filing), detail);
        detail.setMaterials(qualFilingMaterialGateway.listByFilingId(id).stream()
                .map(this::toMaterialCO).collect(Collectors.toList()));
        QualFilingCommitmentEntity commitment = qualFilingCommitmentGateway.getByFilingId(id);
        if (commitment != null) {
            detail.setCommitment(toCommitmentCO(commitment));
        }
        detail.setPersonnelList(qualFilingPersonnelGateway.listByFilingId(id).stream()
                .map(this::toPersonnelCO).collect(Collectors.toList()));
        detail.setEquipmentList(qualFilingEquipmentGateway.listByFilingId(id).stream()
                .map(this::toEquipmentCO).collect(Collectors.toList()));
        return detail;
    }

    public PageResult<QualFilingCO> page(QualFilingPageQuery query) {
        QualFilingQuery domainQuery = new QualFilingQuery();
        domainQuery.setPageNum(query.getCurrent());
        domainQuery.setPageSize(query.getSize());
        domainQuery.setTenantId(AuthUserContextAdapter.getCurrentTenantId());
        if (!query.getSupervision()) {
            domainQuery.setOrgId(query.getOrgId() != null ? query.getOrgId() : resolveOrgId());
        }
        domainQuery.setFilingNo(query.getFilingNo());
        domainQuery.setFilingUnitName(query.getFilingUnitName());
        domainQuery.setFilingStatusCode(query.getFilingStatusCode());
        domainQuery.setApplyTypeCode(query.getApplyTypeCode());
        domainQuery.setFilingTerritoryCode(query.getFilingTerritoryCode());
        domainQuery.setSupervision(query.getSupervision());
        PageResult<QualFilingEntity> pageResult = qualFilingGateway.page(domainQuery);
        List<QualFilingCO> records = pageResult.getRecords().stream()
                .map(entity -> toCO(entity))
                .collect(Collectors.toList());
        return PageResult.of(records, pageResult.getTotal(), pageResult.getPageNum(), pageResult.getPageSize());
    }

    @Transactional
    public void initMaterialTemplate(Long filingId) {
        QualFilingEntity filing = qualFilingGateway.get(filingId);
        statusGuard.ensureEditable(filing);
        List<QualFilingMaterialEntity> existing = qualFilingMaterialGateway.listByFilingId(filingId);
        if (!existing.isEmpty()) {
            return;
        }
        for (QualFilingMaterialEntity template : materialTemplateProvider.buildTemplate(filingId)) {
            qualFilingMaterialGateway.save(template);
        }
    }

    @Transactional
    public QualFilingMaterialCO uploadMaterial(Long id, String attachmentUrl) {
        QualFilingMaterialEntity material = qualFilingMaterialGateway.get(id);
        if (material == null) {
            throw new BizException(ErrorCode.QUAL_FILING_MATERIAL_NOT_FOUND);
        }
        QualFilingEntity filing = qualFilingGateway.get(material.getFilingId());
        statusGuard.ensureEditable(filing);
        material.setAttachmentUrl(attachmentHelper.resolveUrl(attachmentUrl));
        material.setUploadStatusCode(QualFilingMaterialUploadStatusEnum.UPLOADED.getCode());
        material.setUploadStatusName(QualFilingMaterialUploadStatusEnum.UPLOADED.getName());
        return toMaterialCO(qualFilingMaterialGateway.modify(material));
    }

    @Transactional
    public QualFilingCO uploadMainAttachment(Long id, String attachmentUrl) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        statusGuard.ensureEditable(filing);
        filing.setAttachmentUrl(attachmentHelper.resolveUrl(attachmentUrl));
        return toCO(qualFilingGateway.modify(filing));
    }

    @Transactional
    public int batchAddPersonnel(Long filingId, List<Long> sourcePersonnelIds) {
        QualFilingEntity filing = qualFilingGateway.get(filingId);
        statusGuard.ensureEditable(filing);
        return personnelImporter.importFromOrg(filingId, sourcePersonnelIds);
    }

    @Transactional
    public int batchAddEquipment(Long filingId, List<Long> sourceEquipmentIds) {
        QualFilingEntity filing = qualFilingGateway.get(filingId);
        statusGuard.ensureEditable(filing);
        return equipmentImporter.importFromOrg(filingId, sourceEquipmentIds);
    }

    @Transactional
    public Long startChange(Long originFilingId) {
        QualFilingEntity origin = qualFilingGateway.get(originFilingId);
        if (origin == null) {
            throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
        }
        statusGuard.ensureFiled(origin);
        statusGuard.ensureNotChangeReviewing(origin);
        QualFilingEntity draft = cloneFiling(origin);
        draft.setOriginFilingId(originFilingId);
        draft.setApplyTypeCode(QualFilingApplyTypeEnum.CHANGE_DRAFT.getCode());
        draft.setApplyTypeName(QualFilingApplyTypeEnum.CHANGE_DRAFT.getName());
        draft.setFilingStatusCode(QualFilingStatusEnum.DRAFT.getCode());
        draft.setFilingStatusName(QualFilingStatusEnum.DRAFT.getName());
        QualFilingEntity savedDraft = qualFilingGateway.save(draft);
        cloneChildren(originFilingId, savedDraft.getId());
        return savedDraft.getId();
    }

    @Transactional
    public void submitChange(Long draftFilingId) {
        QualFilingEntity draft = qualFilingGateway.get(draftFilingId);
        if (draft == null || draft.getOriginFilingId() == null
                || draft.getApplyTypeCode() == null
                || draft.getApplyTypeCode() != QualFilingApplyTypeEnum.CHANGE_DRAFT.getCode()) {
            throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
        }
        statusGuard.ensureSubmittable(draft);
        QualFilingEntity origin = qualFilingGateway.get(draft.getOriginFilingId());
        statusGuard.ensureNotChangeReviewing(origin);

        QualFilingChangeEntity changeHeader = copyToChangeHeader(origin, draft);
        changeHeader.setChangeFilingId(draftFilingId);
        changeHeader.setSubmitTime(LocalDateTime.now());
        changeHeader.setFilingStatusCode(QualFilingStatusEnum.REVIEWING.getCode());
        changeHeader.setFilingStatusName(QualFilingStatusEnum.REVIEWING.getName());
        QualFilingChangeEntity savedChange = qualFilingChangeGateway.save(changeHeader);

        List<QualFilingChangeDetailEntity> details = changeDiffer.diff(savedChange.getId(), origin, draft);
        if (details.isEmpty()) {
            throw new BizException(ErrorCode.QUAL_FILING_CHANGE_NO_DIFF);
        }
        for (QualFilingChangeDetailEntity detail : details) {
            detail.setCreateName(resolveOperatorName());
            qualFilingChangeDetailGateway.save(detail);
        }

        origin.setFilingStatusCode(QualFilingStatusEnum.CHANGE_REVIEWING.getCode());
        origin.setFilingStatusName(QualFilingStatusEnum.CHANGE_REVIEWING.getName());
        qualFilingGateway.modify(origin);

        draft.setFilingStatusCode(QualFilingStatusEnum.REVIEWING.getCode());
        draft.setFilingStatusName(QualFilingStatusEnum.REVIEWING.getName());
        draft.setSubmitTime(LocalDateTime.now());
        qualFilingGateway.modify(draft);
    }

    @Transactional
    public void approveChange(Long changeId) {
        QualFilingChangeEntity change = qualFilingChangeGateway.get(changeId);
        if (change == null || change.getChangeFilingId() == null) {
            throw new BizException(ErrorCode.QUAL_FILING_CHANGE_NOT_FOUND);
        }
        QualFilingEntity draft = qualFilingGateway.get(change.getChangeFilingId());
        QualFilingEntity origin = qualFilingGateway.get(change.getFilingId());
        applyDraftToOrigin(origin, draft);
        replaceChildrenFromDraft(origin.getId(), draft.getId());
        origin.setFilingStatusCode(QualFilingStatusEnum.FILED.getCode());
        origin.setFilingStatusName(QualFilingStatusEnum.FILED.getName());
        origin.setApproveTime(LocalDateTime.now());
        qualFilingGateway.modify(origin);

        change.setFilingStatusCode(QualFilingStatusEnum.FILED.getCode());
        change.setFilingStatusName(QualFilingStatusEnum.FILED.getName());
        qualFilingChangeGateway.modify(change);
    }

    @Transactional
    public void rejectChange(Long changeId, String rejectReason) {
        QualFilingChangeEntity change = qualFilingChangeGateway.get(changeId);
        if (change == null) {
            throw new BizException(ErrorCode.QUAL_FILING_CHANGE_NOT_FOUND);
        }
        QualFilingEntity origin = qualFilingGateway.get(change.getFilingId());
        origin.setFilingStatusCode(QualFilingStatusEnum.REJECTED.getCode());
        origin.setFilingStatusName(QualFilingStatusEnum.REJECTED.getName());
        origin.setRejectReason(rejectReason);
        qualFilingGateway.modify(origin);

        change.setFilingStatusCode(QualFilingStatusEnum.REJECTED.getCode());
        change.setFilingStatusName(QualFilingStatusEnum.REJECTED.getName());
        change.setRejectReason(rejectReason);
        qualFilingChangeGateway.modify(change);
    }

    public QualFilingChangeHistoryCO getChangeHistory(Long filingId) {
        QualFilingChangeHistoryCO history = new QualFilingChangeHistoryCO();
        int count = qualFilingChangeDetailGateway.countByFilingId(filingId);
        history.setChangeCount(count);
        history.setRecords(qualFilingChangeDetailGateway.listByFilingId(filingId).stream()
                .map(this::toHistoryItem)
                .collect(Collectors.toList()));
        return history;
    }

    private void validateBeforeSubmit(QualFilingEntity filing) {
        List<QualFilingMaterialEntity> materials = qualFilingMaterialGateway.listByFilingId(filing.getId());
        for (QualFilingMaterialEntity material : materials) {
            if (material.getRequiredFlag() != null && material.getRequiredFlag() == 1
                    && !StringUtils.hasText(material.getAttachmentUrl())) {
                throw new BizException(ErrorCode.QUAL_FILING_MATERIAL_INCOMPLETE);
            }
        }
        if (qualFilingCommitmentGateway.getByFilingId(filing.getId()) == null) {
            throw new BizException(ErrorCode.QUAL_FILING_COMMITMENT_REQUIRED);
        }
    }

    private void prefillFromOrgInfo(QualFilingEntity entity) {
        OrgInfoEntity orgInfo = orgInfoGateway.getInfo();
        if (orgInfo == null) {
            return;
        }
        entity.setFilingUnitName(orgInfo.getUnitName());
        entity.setCreditCode(orgInfo.getCreditCode());
        entity.setRegisterAddress(orgInfo.getRegisterAddress());
        entity.setOfficeAddress(orgInfo.getBusinessAddress());
        if (orgInfo.getLegalRepresentative() != null && orgInfo.getLegalRepresentativePhone() != null) {
            entity.setLegalPersonPhone(orgInfo.getLegalRepresentative() + " / " + orgInfo.getLegalRepresentativePhone());
        }
        if (orgInfo.getPrincipalName() != null && orgInfo.getPrincipalPhone() != null) {
            entity.setContactPhone(orgInfo.getPrincipalName() + " / " + orgInfo.getPrincipalPhone());
        }
        entity.setInfoDisclosureUrl(orgInfo.getInfoDisclosureUrl());
        entity.setWorkplaceArea(orgInfo.getWorkplaceArea());
        entity.setArchiveRoomArea(orgInfo.getArchiveRoomArea());
        entity.setFulltimeEvaluatorCount(orgInfo.getFulltimeEvaluatorCount());
        entity.setRegisteredEngineerCount(orgInfo.getRegisteredEngineerCount());
        entity.setFilingTerritoryCode(orgInfo.getDistrictCode());
        entity.setFilingTerritoryName(orgInfo.getDistrictName());
    }

    private void createFiledManageRecord(QualFilingEntity application) {
        QualFilingEntity filed = cloneFiling(application);
        filed.setApplyTypeCode(QualFilingApplyTypeEnum.FILED_MANAGE.getCode());
        filed.setApplyTypeName(QualFilingApplyTypeEnum.FILED_MANAGE.getName());
        filed.setFilingStatusCode(QualFilingStatusEnum.FILED.getCode());
        filed.setFilingStatusName(QualFilingStatusEnum.FILED.getName());
        filed.setOriginFilingId(null);
        QualFilingEntity savedFiled = qualFilingGateway.save(filed);
        cloneChildren(application.getId(), savedFiled.getId());
    }

    private QualFilingEntity cloneFiling(QualFilingEntity source) {
        QualFilingEntity target = new QualFilingEntity();
        BeanUtils.copyProperties(source, target, "id", "originFilingId", "submitTime", "approveTime", "rejectReason");
        target.setOrgId(source.getOrgId());
        target.setTenantId(source.getTenantId());
        return target;
    }

    private void cloneChildren(Long sourceFilingId, Long targetFilingId) {
        for (QualFilingMaterialEntity item : qualFilingMaterialGateway.listByFilingId(sourceFilingId)) {
            QualFilingMaterialEntity copy = new QualFilingMaterialEntity();
            BeanUtils.copyProperties(item, copy, "id");
            copy.setFilingId(targetFilingId);
            qualFilingMaterialGateway.save(copy);
        }
        QualFilingCommitmentEntity commitment = qualFilingCommitmentGateway.getByFilingId(sourceFilingId);
        if (commitment != null) {
            QualFilingCommitmentEntity copy = new QualFilingCommitmentEntity();
            BeanUtils.copyProperties(commitment, copy, "id");
            copy.setFilingId(targetFilingId);
            qualFilingCommitmentGateway.save(copy);
        }
        for (QualFilingPersonnelEntity person : qualFilingPersonnelGateway.listByFilingId(sourceFilingId)) {
            QualFilingPersonnelEntity copyPerson = new QualFilingPersonnelEntity();
            BeanUtils.copyProperties(person, copyPerson, "id");
            copyPerson.setFilingId(targetFilingId);
            qualFilingPersonnelGateway.save(copyPerson);
            for (QualFilingPersonnelCertEntity cert : qualFilingPersonnelCertGateway.listByFilingPersonnelId(person.getId())) {
                QualFilingPersonnelCertEntity copyCert = new QualFilingPersonnelCertEntity();
                BeanUtils.copyProperties(cert, copyCert, "id");
                copyCert.setFilingId(targetFilingId);
                copyCert.setFilingPersonnelId(copyPerson.getId());
                qualFilingPersonnelCertGateway.save(copyCert);
            }
        }
        for (QualFilingEquipmentEntity equipment : qualFilingEquipmentGateway.listByFilingId(sourceFilingId)) {
            QualFilingEquipmentEntity copy = new QualFilingEquipmentEntity();
            BeanUtils.copyProperties(equipment, copy, "id");
            copy.setFilingId(targetFilingId);
            qualFilingEquipmentGateway.save(copy);
        }
    }

    private void replaceChildrenFromDraft(Long originFilingId, Long draftFilingId) {
        clearChildren(originFilingId);
        cloneChildren(draftFilingId, originFilingId);
    }

    private void clearChildren(Long filingId) {
        for (QualFilingMaterialEntity item : qualFilingMaterialGateway.listByFilingId(filingId)) {
            qualFilingMaterialGateway.delete(item.getId());
        }
        QualFilingCommitmentEntity commitment = qualFilingCommitmentGateway.getByFilingId(filingId);
        if (commitment != null) {
            qualFilingCommitmentGateway.physicalDeleteByFilingId(filingId);
        }
        for (QualFilingPersonnelEntity person : qualFilingPersonnelGateway.listByFilingId(filingId)) {
            for (QualFilingPersonnelCertEntity cert : qualFilingPersonnelCertGateway.listByFilingPersonnelId(person.getId())) {
                qualFilingPersonnelCertGateway.delete(cert.getId());
            }
            qualFilingPersonnelGateway.delete(person.getId());
        }
        for (QualFilingEquipmentEntity equipment : qualFilingEquipmentGateway.listByFilingId(filingId)) {
            qualFilingEquipmentGateway.delete(equipment.getId());
        }
    }

    private void applyDraftToOrigin(QualFilingEntity origin, QualFilingEntity draft) {
        origin.setFilingTerritoryCode(draft.getFilingTerritoryCode());
        origin.setFilingTerritoryName(draft.getFilingTerritoryName());
        origin.setFilingUnitName(draft.getFilingUnitName());
        origin.setFilingUnitTypeCode(draft.getFilingUnitTypeCode());
        origin.setFilingUnitTypeName(draft.getFilingUnitTypeName());
        origin.setBusinessScope(draft.getBusinessScope());
        origin.setRegisterAddress(draft.getRegisterAddress());
        origin.setOfficeAddress(draft.getOfficeAddress());
        origin.setCreditCode(draft.getCreditCode());
        origin.setQualCertNo(draft.getQualCertNo());
        origin.setLegalPersonPhone(draft.getLegalPersonPhone());
        origin.setContactPhone(draft.getContactPhone());
        origin.setInfoDisclosureUrl(draft.getInfoDisclosureUrl());
        origin.setFixedAssetAmount(draft.getFixedAssetAmount());
        origin.setArchiveRoomArea(draft.getArchiveRoomArea());
        origin.setFulltimeEvaluatorCount(draft.getFulltimeEvaluatorCount());
        origin.setRegisteredEngineerCount(draft.getRegisteredEngineerCount());
        origin.setWorkplaceArea(draft.getWorkplaceArea());
        origin.setUnitIntro(draft.getUnitIntro());
        origin.setAttachmentUrl(draft.getAttachmentUrl());
        origin.setFilingReviewId(draft.getFilingReviewId());
    }

    private QualFilingChangeEntity copyToChangeHeader(QualFilingEntity origin, QualFilingEntity draft) {
        QualFilingChangeEntity change = new QualFilingChangeEntity();
        change.setOrgId(origin.getOrgId());
        change.setFilingId(origin.getId());
        change.setFilingTerritoryCode(draft.getFilingTerritoryCode());
        change.setFilingTerritoryName(draft.getFilingTerritoryName());
        change.setFilingUnitName(draft.getFilingUnitName());
        change.setFilingUnitTypeCode(draft.getFilingUnitTypeCode());
        change.setFilingUnitTypeName(draft.getFilingUnitTypeName());
        change.setFilingNo(draft.getFilingNo());
        change.setBusinessScope(draft.getBusinessScope());
        change.setRegisterAddress(draft.getRegisterAddress());
        change.setOfficeAddress(draft.getOfficeAddress());
        change.setCreditCode(draft.getCreditCode());
        change.setQualCertNo(draft.getQualCertNo());
        change.setLegalPersonPhone(draft.getLegalPersonPhone());
        change.setContactPhone(draft.getContactPhone());
        change.setInfoDisclosureUrl(draft.getInfoDisclosureUrl());
        change.setFixedAssetAmount(draft.getFixedAssetAmount());
        change.setArchiveRoomArea(draft.getArchiveRoomArea());
        change.setFulltimeEvaluatorCount(draft.getFulltimeEvaluatorCount());
        change.setRegisteredEngineerCount(draft.getRegisteredEngineerCount());
        change.setWorkplaceArea(draft.getWorkplaceArea());
        change.setUnitIntro(draft.getUnitIntro());
        change.setAttachmentUrl(draft.getAttachmentUrl());
        change.setTenantId(origin.getTenantId());
        return change;
    }

    private void applyModifyFields(QualFilingEntity entity, QualFilingModifyCmd cmd) {
        if (cmd.getFilingTerritoryCode() != null) {
            entity.setFilingTerritoryCode(cmd.getFilingTerritoryCode());
        }
        if (cmd.getFilingTerritoryName() != null) {
            entity.setFilingTerritoryName(cmd.getFilingTerritoryName());
        }
        if (cmd.getFilingUnitName() != null) {
            entity.setFilingUnitName(cmd.getFilingUnitName());
        }
        if (cmd.getFilingUnitTypeCode() != null) {
            entity.setFilingUnitTypeCode(cmd.getFilingUnitTypeCode());
        }
        if (cmd.getFilingUnitTypeName() != null) {
            entity.setFilingUnitTypeName(cmd.getFilingUnitTypeName());
        }
        if (cmd.getFilingNo() != null) {
            entity.setFilingNo(cmd.getFilingNo());
        }
        if (cmd.getBusinessScope() != null) {
            entity.setBusinessScope(cmd.getBusinessScope());
        }
        if (cmd.getRegisterAddress() != null) {
            entity.setRegisterAddress(cmd.getRegisterAddress());
        }
        if (cmd.getOfficeAddress() != null) {
            entity.setOfficeAddress(cmd.getOfficeAddress());
        }
        if (cmd.getCreditCode() != null) {
            entity.setCreditCode(cmd.getCreditCode());
        }
        if (cmd.getQualCertNo() != null) {
            entity.setQualCertNo(cmd.getQualCertNo());
        }
        if (cmd.getLegalPersonPhone() != null) {
            entity.setLegalPersonPhone(cmd.getLegalPersonPhone());
        }
        if (cmd.getContactPhone() != null) {
            entity.setContactPhone(cmd.getContactPhone());
        }
        if (cmd.getInfoDisclosureUrl() != null) {
            entity.setInfoDisclosureUrl(cmd.getInfoDisclosureUrl());
        }
        if (cmd.getFixedAssetAmount() != null) {
            entity.setFixedAssetAmount(cmd.getFixedAssetAmount());
        }
        if (cmd.getArchiveRoomArea() != null) {
            entity.setArchiveRoomArea(cmd.getArchiveRoomArea());
        }
        if (cmd.getFulltimeEvaluatorCount() != null) {
            entity.setFulltimeEvaluatorCount(cmd.getFulltimeEvaluatorCount());
        }
        if (cmd.getRegisteredEngineerCount() != null) {
            entity.setRegisteredEngineerCount(cmd.getRegisteredEngineerCount());
        }
        if (cmd.getWorkplaceArea() != null) {
            entity.setWorkplaceArea(cmd.getWorkplaceArea());
        }
        if (cmd.getUnitIntro() != null) {
            entity.setUnitIntro(cmd.getUnitIntro());
        }
        if (cmd.getAttachmentUrl() != null) {
            entity.setAttachmentUrl(cmd.getAttachmentUrl());
        }
        if (cmd.getFilingReviewId() != null) {
            entity.setFilingReviewId(cmd.getFilingReviewId());
        }
    }

    private QualFilingChangeHistoryItemCO toHistoryItem(QualFilingChangeDetailEntity entity) {
        QualFilingChangeHistoryItemCO item = new QualFilingChangeHistoryItemCO();
        item.setId(entity.getId());
        item.setChangeItemName(StringUtils.hasText(entity.getFormStepName())
                ? entity.getFormStepName() : entity.getChangeItemName());
        item.setChangeTime(entity.getCreateTime());
        item.setOperatorName(StringUtils.hasText(entity.getCreateName()) ? entity.getCreateName() : resolveOperatorName());
        return item;
    }

    private String resolveOperatorName() {
        String userName = AuthUserContextAdapter.getCurrentUserName();
        return StringUtils.hasText(userName) ? userName : "系统";
    }

    private QualFilingCO toCO(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;
    }

    private QualFilingMaterialCO toMaterialCO(QualFilingMaterialEntity entity) {
        QualFilingMaterialCO co = new QualFilingMaterialCO();
        co.setId(entity.getId());
        co.setFilingId(entity.getFilingId());
        co.setMaterialContent(entity.getMaterialContent());
        co.setMaterialFormat(entity.getMaterialFormat());
        co.setSortOrder(entity.getSortOrder());
        co.setRequiredFlag(entity.getRequiredFlag());
        co.setUploadStatusCode(entity.getUploadStatusCode());
        co.setUploadStatusName(entity.getUploadStatusName());
        co.setAttachmentDesc(entity.getAttachmentDesc());
        co.setAttachmentUrl(entity.getAttachmentUrl());
        co.setMaterialType(entity.getMaterialType());
        co.setMaterialRemark(entity.getMaterialRemark());
        co.setTenantId(entity.getTenantId());
        return co;
    }

    private QualFilingCommitmentCO toCommitmentCO(QualFilingCommitmentEntity entity) {
        QualFilingCommitmentCO co = new QualFilingCommitmentCO();
        co.setId(entity.getId());
        co.setFilingId(entity.getFilingId());
        co.setCommitmentContent(entity.getCommitmentContent());
        co.setLegalRepSignatureUrl(entity.getLegalRepSignatureUrl());
        co.setSignDate(entity.getSignDate());
        co.setLegalRepPersonnelId(entity.getLegalRepPersonnelId());
        co.setLegalRepName(entity.getLegalRepName());
        co.setTenantId(entity.getTenantId());
        return co;
    }

    private QualFilingPersonnelCO toPersonnelCO(QualFilingPersonnelEntity entity) {
        QualFilingPersonnelCO co = new QualFilingPersonnelCO();
        co.setId(entity.getId());
        co.setFilingId(entity.getFilingId());
        co.setSourcePersonnelId(entity.getSourcePersonnelId());
        co.setPersonName(entity.getPersonName());
        co.setPersonTypeCode(entity.getPersonTypeCode());
        co.setPersonTypeName(entity.getPersonTypeName());
        co.setPositionName(entity.getPositionName());
        co.setTitleName(entity.getTitleName());
        co.setGenderCode(entity.getGenderCode());
        co.setGenderName(entity.getGenderName());
        co.setBirthDate(entity.getBirthDate());
        co.setJoinWorkDate(entity.getJoinWorkDate());
        co.setIdCardNo(entity.getIdCardNo());
        co.setCurrentAddress(entity.getCurrentAddress());
        co.setOfficeAddress(entity.getOfficeAddress());
        co.setEducationCode(entity.getEducationCode());
        co.setEducationName(entity.getEducationName());
        co.setGraduateSchool(entity.getGraduateSchool());
        co.setMajor(entity.getMajor());
        co.setQualScope(entity.getQualScope());
        co.setPublications(entity.getPublications());
        co.setProfessionalLevelCert(entity.getProfessionalLevelCert());
        co.setRegisterEngineerFlag(entity.getRegisterEngineerFlag());
        co.setAbilityDeclaration(entity.getAbilityDeclaration());
        co.setWorkExperience(entity.getWorkExperience());
        co.setProofMaterialUrl(entity.getProofMaterialUrl());
        co.setTenantId(entity.getTenantId());
        return co;
    }

    private QualFilingEquipmentCO toEquipmentCO(QualFilingEquipmentEntity entity) {
        QualFilingEquipmentCO co = new QualFilingEquipmentCO();
        co.setId(entity.getId());
        co.setFilingId(entity.getFilingId());
        co.setSourceEquipmentId(entity.getSourceEquipmentId());
        co.setDeviceName(entity.getDeviceName());
        co.setDeviceModel(entity.getDeviceModel());
        co.setInstrumentTypeCode(entity.getInstrumentTypeCode());
        co.setInstrumentTypeName(entity.getInstrumentTypeName());
        co.setDeviceTypeCode(entity.getDeviceTypeCode());
        co.setDeviceTypeName(entity.getDeviceTypeName());
        co.setManufacturer(entity.getManufacturer());
        co.setFlowDesc(entity.getFlowDesc());
        co.setMinFlow(entity.getMinFlow());
        co.setMaxFlow(entity.getMaxFlow());
        co.setCalibrationUnit(entity.getCalibrationUnit());
        co.setCalibrationInitValue(entity.getCalibrationInitValue());
        co.setFieldCalibrationTypeCode(entity.getFieldCalibrationTypeCode());
        co.setFieldCalibrationTypeName(entity.getFieldCalibrationTypeName());
        co.setDualChannelFlag(entity.getDualChannelFlag());
        co.setCalibrationReportUrl(entity.getCalibrationReportUrl());
        co.setTenantId(entity.getTenantId());
        return co;
    }

    /**
     * 合规检查：根据备案ID逐项检查是否满足法规要求
     */
    public List<QualFilingComplianceCheckResultCO> complianceCheck(Long id) {
        QualFilingEntity filing = qualFilingGateway.get(id);
        if (filing == null) {
            throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
        }

        List<QualFilingComplianceCheckResultCO> results = new ArrayList<>();

        // 1. 主体资格
        results.add(checkMainQualification(filing));

        // 2. 场所与设备
        results.add(checkWorkplace(filing));

        // 3. 人员数量与结构
        results.add(checkPersonnelCount(id));

        // 4. 人员资历
        results.add(checkPersonnelExperience(id));

        // 5. 关键岗位要求（暂默认通过，标记警告）
        results.add(buildResult(QualFilingComplianceCheckEnum.KEY_POSITION,
                QualFilingComplianceCheckEnum.STATUS_WARN));

        // 6. 管理体系（暂无法判断，标记警告）
        results.add(buildResult(QualFilingComplianceCheckEnum.MANAGEMENT_SYSTEM,
                QualFilingComplianceCheckEnum.STATUS_WARN));

        // 7. 责任承诺
        results.add(checkCommitment(id));

        // 8. 信息公开
        results.add(checkInfoDisclosure(filing));

        // 9. 信用记录
        results.add(checkCreditRecord(id));

        // 10. 其他
        results.add(buildResult(QualFilingComplianceCheckEnum.OTHER,
                QualFilingComplianceCheckEnum.STATUS_PASS));

        return results;
    }

    /**
     * 主体资格：固定资产 >= 1000万元
     */
    private QualFilingComplianceCheckResultCO checkMainQualification(QualFilingEntity filing) {
        // 1000万元 = 10,000,000元 = 1,000,000,000分
        boolean pass = filing.getFixedAssetAmount() != null
                && filing.getFixedAssetAmount() >= 1_000_000_000L;
        return buildResult(QualFilingComplianceCheckEnum.MAIN_QUALIFICATION,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 场所与设备：工作场所建筑面积 >= 1000㎡
     */
    private QualFilingComplianceCheckResultCO checkWorkplace(QualFilingEntity filing) {
        boolean pass = filing.getWorkplaceArea() != null
                && filing.getWorkplaceArea()
                .compareTo(new BigDecimal(QualFilingComplianceCheckEnum.WORKPLACE_LOWER)) >= 0;
        return buildResult(QualFilingComplianceCheckEnum.WORKPLACE,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 人员数量与结构：专职技术人员 >= 25人，中级注安师 >= 30%
     */
    private QualFilingComplianceCheckResultCO checkPersonnelCount(Long filingId) {
        int total = qualFilingPersonnelGateway.countByFilingId(filingId);
        if (total == 0) {
            return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
                    QualFilingComplianceCheckEnum.STATUS_FAIL);
        }
        int engineerCount = qualFilingPersonnelGateway.countByFilingIdAndRegisterEngineerFlag(filingId, 1);
        boolean pass = total >= QualFilingComplianceCheckEnum.PERSONNEL_COUNT_LOWER
                && engineerCount * 100 / total >= QualFilingComplianceCheckEnum.PERSONNEL_RATE;
        return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 人员资历：所有专职技术人员在本行业领域工作二年以上
     */
    private QualFilingComplianceCheckResultCO checkPersonnelExperience(Long filingId) {
        int total = qualFilingPersonnelGateway.countByFilingId(filingId);
        if (total == 0) {
            return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
                    QualFilingComplianceCheckEnum.STATUS_FAIL);
        }
        LocalDate threshold = LocalDate.now().minusYears(2);
        boolean allQualified = qualFilingPersonnelGateway.countByFilingIdAndJoinWorkDateAfter(filingId, threshold) == 0;
        return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
                allQualified ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 责任承诺：qual_filing_commitment 表是否有数据
     */
    private QualFilingComplianceCheckResultCO checkCommitment(Long filingId) {
        QualFilingCommitmentEntity commitment =
                qualFilingCommitmentGateway.getByFilingId(filingId);
        return buildResult(QualFilingComplianceCheckEnum.COMMITMENT,
                commitment != null ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 信息公开：info_disclosure_url 是否已填写
     */
    private QualFilingComplianceCheckResultCO checkInfoDisclosure(QualFilingEntity filing) {
        boolean pass = filing.getInfoDisclosureUrl() != null
                && !filing.getInfoDisclosureUrl().isEmpty();
        return buildResult(QualFilingComplianceCheckEnum.INFO_DISCLOSURE,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 信用记录：qual_filing_material 表 upload_status_code=2 且 material_type=4
     */
    private QualFilingComplianceCheckResultCO checkCreditRecord(Long filingId) {
        int count = qualFilingMaterialGateway.countByFilingIdAndUploadStatusCodeAndMaterialType(
                filingId,
                QualFilingMaterialUploadStatusEnum.UPLOADED.getCode(),
                MaterialTypeEnum.NO_VIOLATION_RECORD.getCode());
        return buildResult(QualFilingComplianceCheckEnum.CREDIT_RECORD,
                count > 0 ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    private QualFilingComplianceCheckResultCO buildResult(QualFilingComplianceCheckEnum item, String status) {
        QualFilingComplianceCheckResultCO co = new QualFilingComplianceCheckResultCO();
        co.setTitle(item.getTitle());
        co.setDescription(item.getDescription());
        co.setStatus(status);
        return co;
    }

    /**
     * 备案变更合规检查：根据变更ID逐项检查是否满足法规要求
     */
    public List<QualFilingChangeComplianceCheckResultCO> complianceCheckChange(Long changeId) {
        QualFilingChangeEntity change = qualFilingChangeGateway.get(changeId);
        if (change == null) {
            throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
        }

        List<QualFilingChangeComplianceCheckResultCO> results = new ArrayList<>();

        // 1. 主体资格
        results.add(checkMainQualificationChange(change));

        // 2. 场所与设备
        results.add(checkWorkplaceChange(change));

        // 3. 人员数量与结构
        results.add(checkPersonnelCountChange(changeId));

        // 4. 人员资历
        results.add(checkPersonnelExperienceChange(changeId));

        // 5. 关键岗位要求（暂默认通过，标记警告）
        results.add(buildChangeResult(QualFilingComplianceCheckEnum.KEY_POSITION,
                QualFilingComplianceCheckEnum.STATUS_WARN));

        // 6. 管理体系（暂无法判断，标记警告）
        results.add(buildChangeResult(QualFilingComplianceCheckEnum.MANAGEMENT_SYSTEM,
                QualFilingComplianceCheckEnum.STATUS_WARN));

        // 7. 责任承诺
        results.add(checkCommitmentChange(changeId));

        // 8. 信息公开
        results.add(checkInfoDisclosureChange(change));

        // 9. 信用记录
        results.add(checkCreditRecordChange(changeId));

        // 10. 其他
        results.add(buildChangeResult(QualFilingComplianceCheckEnum.OTHER,
                QualFilingComplianceCheckEnum.STATUS_PASS));

        return results;
    }

    /**
     * 主体资格：固定资产 >= 1000万元
     */
    private QualFilingChangeComplianceCheckResultCO checkMainQualificationChange(QualFilingChangeEntity change) {
        boolean pass = change.getFixedAssetAmount() != null
                && change.getFixedAssetAmount() >= 1_000_000_000L;
        return buildChangeResult(QualFilingComplianceCheckEnum.MAIN_QUALIFICATION,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 场所与设备：工作场所建筑面积 >= 1000㎡
     */
    private QualFilingChangeComplianceCheckResultCO checkWorkplaceChange(QualFilingChangeEntity change) {
        boolean pass = change.getWorkplaceArea() != null
                && change.getWorkplaceArea()
                .compareTo(new BigDecimal(QualFilingComplianceCheckEnum.WORKPLACE_LOWER)) >= 0;
        return buildChangeResult(QualFilingComplianceCheckEnum.WORKPLACE,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 人员数量与结构：专职技术人员 >= 25人，中级注安师 >= 30%
     */
    private QualFilingChangeComplianceCheckResultCO checkPersonnelCountChange(Long filingId) {
        int total = qualFilingPersonnelChangeGateway.countByFilingId(filingId);
        if (total == 0) {
            return buildChangeResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
                    QualFilingComplianceCheckEnum.STATUS_FAIL);
        }
        int engineerCount = qualFilingPersonnelChangeGateway.countByFilingIdAndRegisterEngineerFlag(filingId, 1);
        boolean pass = total >= QualFilingComplianceCheckEnum.PERSONNEL_COUNT_LOWER
                && engineerCount * 100 / total >= QualFilingComplianceCheckEnum.PERSONNEL_RATE;
        return buildChangeResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 人员资历：所有专职技术人员在本行业领域工作二年以上
     */
    private QualFilingChangeComplianceCheckResultCO checkPersonnelExperienceChange(Long filingId) {
        int total = qualFilingPersonnelChangeGateway.countByFilingId(filingId);
        if (total == 0) {
            return buildChangeResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
                    QualFilingComplianceCheckEnum.STATUS_FAIL);
        }
        LocalDate threshold = LocalDate.now().minusYears(2);
        boolean allQualified = qualFilingPersonnelChangeGateway.countByFilingIdAndJoinWorkDateAfter(filingId, threshold) == 0;
        return buildChangeResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
                allQualified ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 责任承诺：qual_filing_commitment_change 表是否有数据
     */
    private QualFilingChangeComplianceCheckResultCO checkCommitmentChange(Long filingId) {
        QualFilingCommitmentChangeE commitment =
                qualFilingCommitmentChangeGateway.getByFilingId(filingId);
        return buildChangeResult(QualFilingComplianceCheckEnum.COMMITMENT,
                commitment != null ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 信息公开：info_disclosure_url 是否已填写
     */
    private QualFilingChangeComplianceCheckResultCO checkInfoDisclosureChange(QualFilingChangeEntity change) {
        boolean pass = change.getInfoDisclosureUrl() != null
                && !change.getInfoDisclosureUrl().isEmpty();
        return buildChangeResult(QualFilingComplianceCheckEnum.INFO_DISCLOSURE,
                pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    /**
     * 信用记录：qual_filing_material_change 表 upload_status_code=2 且 material_type=4
     */
    private QualFilingChangeComplianceCheckResultCO checkCreditRecordChange(Long filingId) {
        int count = qualFilingMaterialChangeGateway.countByFilingIdAndUploadStatusCodeAndMaterialType(
                filingId,
                QualFilingMaterialUploadStatusEnum.UPLOADED.getCode(),
                String.valueOf(MaterialTypeEnum.NO_VIOLATION_RECORD.getCode()));
        return buildChangeResult(QualFilingComplianceCheckEnum.CREDIT_RECORD,
                count > 0 ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
    }

    private QualFilingChangeComplianceCheckResultCO buildChangeResult(QualFilingComplianceCheckEnum item, String status) {
        QualFilingChangeComplianceCheckResultCO co = new QualFilingChangeComplianceCheckResultCO();
        co.setTitle(item.getTitle());
        co.setDescription(item.getDescription());
        co.setStatus(status);
        return co;
    }

    private Long resolveOrgId() {
        return orgContextResolver.resolveOrgId(null);
    }

    private Long resolveTenantId() {
        Long tenantId = AuthUserContextAdapter.getCurrentTenantId();
        if (tenantId != null) {
            return tenantId;
        }
        return fallbackTenantId != null && fallbackTenantId > 0 ? fallbackTenantId : null;
    }
}
