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.entity.QualFilingEntity;
import org.qinan.safetyeval.domain.gateway.QualFilingGateway;
import org.qinan.safetyeval.domain.query.QualFilingQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.infrastructure.dataobject.QualFilingDO;
import org.qinan.safetyeval.infrastructure.mapper.QualFilingMapper;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

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

/**
 * 资质备案申请Gateway实现（Infrastructure层）
 *
 * @author safety-eval
 */
@Component
public class QualFilingGatewayImpl implements QualFilingGateway {

    private static final String SCENE_CHANGE = "change";

    private static final int APPLY_TYPE_APPLICATION = 1;
    private static final int APPLY_TYPE_FILED_MANAGE = 3;
    private static final int STATUS_FILED = 1;
    private static final int STATUS_CHANGE_REVIEWING = 4;

    @Resource
    private QualFilingMapper qualFilingMapper;

    @Override
    public QualFilingEntity save(QualFilingEntity entity) {
        QualFilingDO dataObject = toDO(entity);
        InsertFieldDefaults.apply(dataObject);
        qualFilingMapper.insert(dataObject);
        entity.setId(dataObject.getId());
        return entity;
    }

    @Override
    public QualFilingEntity get(Long id) {
        QualFilingDO dataObject = qualFilingMapper.selectById(id);
        return toEntity(dataObject);
    }
@Override
    public QualFilingEntity getByFilingNo(String filingNo) {
        LambdaQueryWrapper<QualFilingDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QualFilingDO::getFilingNo, filingNo);
        wrapper.eq(QualFilingDO::getDeleteEnum, "false");
        QualFilingDO dataObject = qualFilingMapper.selectOne(wrapper);
        return toEntity(dataObject);
    }

    @Override
    public QualFilingEntity modify(QualFilingEntity entity) {
        QualFilingDO dataObject = toDO(entity);
        dataObject.setId(entity.getId());
        InsertFieldDefaults.applyForUpdate(dataObject);
        qualFilingMapper.updateById(dataObject);
        return get(entity.getId());
    }

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

    @Override
    public PageResult<QualFilingEntity> page(QualFilingQuery query) {
        LambdaQueryWrapper<QualFilingDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QualFilingDO::getDeleteEnum, "false");
        if (query.getOrgId() != null) {
            wrapper.eq(QualFilingDO::getOrgId, query.getOrgId());
        }
        if (StringUtils.hasText(query.getFilingNo())) {
            wrapper.eq(QualFilingDO::getFilingNo, query.getFilingNo());
        }
        if (StringUtils.hasText(query.getFilingUnitName())) {
            wrapper.like(QualFilingDO::getFilingUnitName, query.getFilingUnitName());
        }
        if (StringUtils.hasText(query.getFilingTerritoryCode())) {
            wrapper.eq(QualFilingDO::getFilingTerritoryCode, query.getFilingTerritoryCode());
        }
        if (SCENE_CHANGE.equals(query.getScene())) {
            applyChangeListFilter(wrapper, query);
        }
        else {
            if (query.getFilingStatusCodes() != null && !query.getFilingStatusCodes().isEmpty()) {
                wrapper.in(QualFilingDO::getFilingStatusCode, query.getFilingStatusCodes());
            }
            else if (query.getFilingStatusCode() != null) {
                wrapper.eq(QualFilingDO::getFilingStatusCode, query.getFilingStatusCode());
            }
            if (query.getApplyTypeCode() != null) {
                wrapper.eq(QualFilingDO::getApplyTypeCode, query.getApplyTypeCode());
                if (query.getApplyTypeCode() == APPLY_TYPE_FILED_MANAGE) {
                    wrapper.isNull(QualFilingDO::getOriginFilingId);
                }
            }
        }
        wrapper.orderByDesc(QualFilingDO::getCreateTime);

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

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

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

    /**
     * 备案变更列表：优先展示已备案主记录(applyType=3)；
     * 若仅有资质备案申请(applyType=1)为已备案、尚无主记录时，回退展示申请单。
     */
    private void applyChangeListFilter(LambdaQueryWrapper<QualFilingDO> wrapper, QualFilingQuery query) {
        List<Integer> statuses = resolveStatusFilter(query, Arrays.asList(STATUS_FILED, STATUS_CHANGE_REVIEWING));
        wrapper.and(w -> {
            w.nested(n -> n
                    .eq(QualFilingDO::getApplyTypeCode, APPLY_TYPE_FILED_MANAGE)
                    .isNull(QualFilingDO::getOriginFilingId)
                    .in(QualFilingDO::getFilingStatusCode, statuses));
            if (statuses.contains(STATUS_FILED)) {
                w.or(n -> n
                        .eq(QualFilingDO::getApplyTypeCode, APPLY_TYPE_APPLICATION)
                        .eq(QualFilingDO::getFilingStatusCode, STATUS_FILED)
                        .apply("NOT EXISTS (SELECT 1 FROM qual_filing f2 WHERE f2.org_id = qual_filing.org_id"
                                + " AND f2.apply_type_code = " + APPLY_TYPE_FILED_MANAGE
                                + " AND f2.origin_filing_id IS NULL"
                                + " AND f2.delete_enum = 'false'"
                                + " AND f2.filing_status_code IN (" + STATUS_FILED + "," + STATUS_CHANGE_REVIEWING + "))"));
            }
        });
    }

    private List<Integer> resolveStatusFilter(QualFilingQuery query, List<Integer> defaults) {
        if (query.getFilingStatusCodes() != null && !query.getFilingStatusCodes().isEmpty()) {
            return query.getFilingStatusCodes();
        }
        if (query.getFilingStatusCode() != null) {
            return Collections.singletonList(query.getFilingStatusCode());
        }
        return new ArrayList<>(defaults);
    }

    private QualFilingDO toDO(QualFilingEntity entity) {
        QualFilingDO dataObject = new QualFilingDO();
        dataObject.setOrgId(entity.getOrgId());
        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.setOriginFilingId(entity.getOriginFilingId());
        dataObject.setRejectReason(entity.getRejectReason());
        dataObject.setSubmitTime(entity.getSubmitTime());
        dataObject.setApproveTime(entity.getApproveTime());
        dataObject.setFilingStatusCode(entity.getFilingStatusCode());
        dataObject.setFilingStatusName(entity.getFilingStatusName());
        dataObject.setApplyTypeCode(entity.getApplyTypeCode());
        dataObject.setApplyTypeName(entity.getApplyTypeName());
        dataObject.setTenantId(entity.getTenantId());
        return dataObject;
    }

    private QualFilingEntity toEntity(QualFilingDO dataObject) {
        if (dataObject == null) {
            return null;
        }
        QualFilingEntity entity = new QualFilingEntity();
        entity.setId(dataObject.getId());
        entity.setOrgId(dataObject.getOrgId());
        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.setOriginFilingId(dataObject.getOriginFilingId());
        entity.setRejectReason(dataObject.getRejectReason());
        entity.setSubmitTime(dataObject.getSubmitTime());
        entity.setApproveTime(dataObject.getApproveTime());
        entity.setFilingStatusCode(dataObject.getFilingStatusCode());
        entity.setFilingStatusName(dataObject.getFilingStatusName());
        entity.setApplyTypeCode(dataObject.getApplyTypeCode());
        entity.setApplyTypeName(dataObject.getApplyTypeName());
        entity.setTenantId(dataObject.getTenantId());
        return entity;
    }
}
