package org.qinan.safetyeval.app.support;

import org.qinan.safetyeval.domain.constant.QualFilingFormStepEnum;
import org.qinan.safetyeval.domain.entity.QualFilingChangeDetailEntity;
import org.qinan.safetyeval.domain.entity.QualFilingCommitmentEntity;
import org.qinan.safetyeval.domain.entity.QualFilingEntity;
import org.qinan.safetyeval.domain.entity.QualFilingEquipmentEntity;
import org.qinan.safetyeval.domain.entity.QualFilingPersonnelEntity;
import org.qinan.safetyeval.domain.gateway.QualFilingCommitmentGateway;
import org.qinan.safetyeval.domain.gateway.QualFilingEquipmentGateway;
import org.qinan.safetyeval.domain.gateway.QualFilingMaterialGateway;
import org.qinan.safetyeval.domain.gateway.QualFilingPersonnelGateway;
import org.springframework.stereotype.Component;

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

/**
 * 对比原备案与变更草稿，按 5 步表单产出变更明细
 */
@Component
public class QualFilingChangeDiffer {

    @Resource
    private QualFilingMaterialGateway qualFilingMaterialGateway;

    @Resource
    private QualFilingCommitmentGateway qualFilingCommitmentGateway;

    @Resource
    private QualFilingPersonnelGateway qualFilingPersonnelGateway;

    @Resource
    private QualFilingEquipmentGateway qualFilingEquipmentGateway;

        public List<QualFilingChangeDetailEntity> diff(Long changeId, QualFilingEntity origin, QualFilingEntity draft) {
        List<QualFilingChangeDetailEntity> details = new ArrayList<>();
        if (basicInfoChanged(origin, draft)) {
            details.add(stepDetail(changeId, QualFilingFormStepEnum.BASIC_INFO, "备案基本信息变更",
                    summarizeBasic(origin), summarizeBasic(draft)));
        }
        if (materialsChanged(origin.getId(), draft.getId())) {
            details.add(stepDetail(changeId, QualFilingFormStepEnum.MATERIALS, "备案材料上传变更", "材料清单", "材料清单已变更"));
        }
        if (commitmentChanged(origin.getId(), draft.getId())) {
            details.add(stepDetail(changeId, QualFilingFormStepEnum.COMMITMENT, "法定代表人承诺书变更", "承诺书", "承诺书已变更"));
        }
        if (personnelChanged(origin.getId(), draft.getId())) {
            details.add(stepDetail(changeId, QualFilingFormStepEnum.PERSONNEL, "备案人员管理变更", "人员清单", "人员清单已变更"));
        }
        if (equipmentChanged(origin.getId(), draft.getId())) {
            details.add(stepDetail(changeId, QualFilingFormStepEnum.EQUIPMENT, "装备清单变更", "装备清单", "装备清单已变更"));
        }
        return details;
    }

    private boolean basicInfoChanged(QualFilingEntity origin, QualFilingEntity draft) {
        return !Objects.equals(origin.getFilingTerritoryCode(), draft.getFilingTerritoryCode())
                || !Objects.equals(origin.getBusinessScope(), draft.getBusinessScope())
                || !Objects.equals(origin.getRegisterAddress(), draft.getRegisterAddress())
                || !Objects.equals(origin.getOfficeAddress(), draft.getOfficeAddress())
                || !Objects.equals(origin.getCreditCode(), draft.getCreditCode())
                || !Objects.equals(origin.getQualCertNo(), draft.getQualCertNo())
                || !Objects.equals(origin.getLegalPersonPhone(), draft.getLegalPersonPhone())
                || !Objects.equals(origin.getContactPhone(), draft.getContactPhone())
                || !Objects.equals(origin.getInfoDisclosureUrl(), draft.getInfoDisclosureUrl())
                || !Objects.equals(origin.getFixedAssetAmount(), draft.getFixedAssetAmount())
                || !Objects.equals(origin.getArchiveRoomArea(), draft.getArchiveRoomArea())
                || !Objects.equals(origin.getFulltimeEvaluatorCount(), draft.getFulltimeEvaluatorCount())
                || !Objects.equals(origin.getRegisteredEngineerCount(), draft.getRegisteredEngineerCount())
                || !Objects.equals(origin.getWorkplaceArea(), draft.getWorkplaceArea())
                || !Objects.equals(origin.getUnitIntro(), draft.getUnitIntro())
                || !Objects.equals(origin.getAttachmentUrl(), draft.getAttachmentUrl());
    }

    private String summarizeBasic(QualFilingEntity entity) {
        return entity.getFilingUnitName() + "|" + entity.getBusinessScope();
    }

    private boolean materialsChanged(Long originId, Long draftId) {
        return !materialSignature(originId).equals(materialSignature(draftId));
    }

    private String materialSignature(Long filingId) {
        return qualFilingMaterialGateway.listByFilingId(filingId).stream()
                .map(m -> m.getMaterialContent() + ":" + m.getAttachmentUrl())
                .sorted()
                .collect(Collectors.joining(";"));
    }

    private boolean commitmentChanged(Long originId, Long draftId) {
        QualFilingCommitmentEntity o = qualFilingCommitmentGateway.getByFilingId(originId);
        QualFilingCommitmentEntity d = qualFilingCommitmentGateway.getByFilingId(draftId);
        return !Objects.equals(commitmentSig(o), commitmentSig(d));
    }

    private String commitmentSig(QualFilingCommitmentEntity entity) {
        if (entity == null) {
            return "";
        }
        return entity.getCommitmentContent() + "|" + entity.getLegalRepSignatureUrl() + "|" + entity.getSignDate()
                + "|" + entity.getLegalRepPersonnelId() + "|" + entity.getLegalRepName();
    }

    private boolean personnelChanged(Long originId, Long draftId) {
        return !personnelSignature(originId).equals(personnelSignature(draftId));
    }

    private String personnelSignature(Long filingId) {
        return qualFilingPersonnelGateway.listByFilingId(filingId).stream()
                .map(QualFilingPersonnelEntity::getSourcePersonnelId)
                .map(String::valueOf)
                .sorted()
                .collect(Collectors.joining(","));
    }

    private boolean equipmentChanged(Long originId, Long draftId) {
        return !equipmentSignature(originId).equals(equipmentSignature(draftId));
    }

    private String equipmentSignature(Long filingId) {
        return qualFilingEquipmentGateway.listByFilingId(filingId).stream()
                .map(e -> e.getSourceEquipmentId() + ":" + e.getCalibrationReportUrl())
                .sorted()
                .collect(Collectors.joining(";"));
    }

    private QualFilingChangeDetailEntity stepDetail(Long changeId, QualFilingFormStepEnum step,
                                                    String content, String before, String after) {
        QualFilingChangeDetailEntity detail = new QualFilingChangeDetailEntity();
        detail.setChangeId(changeId);
        detail.setFormStepCode(step.getCode());
        detail.setFormStepName(step.getName());
        detail.setChangeField("step:" + step.getCode());
        detail.setChangeContent(content);
        detail.setChangeItemName(step.getName());
        detail.setBeforeValue(before);
        detail.setAfterValue(after);
        return detail;
    }
}
