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.OrgResignApplyEntity;
import org.qinan.safetyeval.domain.gateway.OrgResignApplyGateway;
import org.qinan.safetyeval.domain.query.OrgResignApplyQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.infrastructure.dataobject.OrgResignApplyDO;
import org.qinan.safetyeval.infrastructure.mapper.OrgResignApplyMapper;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.qinan.safetyeval.infrastructure.support.OrgContextResolver;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

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

/**
 * 人员离职申请Gateway实现（Infrastructure层）
 *
 * @author safety-eval
 */
@Component
public class OrgResignApplyGatewayImpl implements OrgResignApplyGateway {

    @Resource
    private OrgResignApplyMapper orgResignApplyMapper;

    @Resource
    private OrgContextResolver orgContextResolver;

    @Override
    public OrgResignApplyEntity save(OrgResignApplyEntity entity) {
        OrgResignApplyDO dataObject = toDO(entity);
        InsertFieldDefaults.apply(dataObject);
        orgResignApplyMapper.insert(dataObject);
        entity.setId(dataObject.getId());
        return entity;
    }

    @Override
    public OrgResignApplyEntity get(Long id) {
        OrgResignApplyDO dataObject = orgResignApplyMapper.selectById(id);
        return toEntity(dataObject);
    }

    @Override
    public OrgResignApplyEntity modify(OrgResignApplyEntity entity) {
        OrgResignApplyDO dataObject = toDO(entity);
        dataObject.setId(entity.getId());
        InsertFieldDefaults.applyForUpdate(dataObject);
        orgResignApplyMapper.updateById(dataObject);
        return get(entity.getId());
    }

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

    @Override
    public PageResult<OrgResignApplyEntity> page(OrgResignApplyQuery query) {
        LambdaQueryWrapper<OrgResignApplyDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrgResignApplyDO::getDeleteEnum, "false");
        if (query.getOrgId() != null) {
            wrapper.eq(OrgResignApplyDO::getOrgId, query.getOrgId());
        }
        if (query.getPersonnelId() != null) {
            wrapper.eq(OrgResignApplyDO::getPersonnelId, query.getPersonnelId());
        }
        if (query.getAuditStatusCode() != null) {
            wrapper.eq(OrgResignApplyDO::getAuditStatusCode, query.getAuditStatusCode());
        }
        if (StringUtils.hasText(query.getApplicantName())) {
            wrapper.like(OrgResignApplyDO::getApplicantName, query.getApplicantName());
        }

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

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

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

    @Override
    public List<OrgResignApplyEntity> listByPersonnelId(Long personnelId) {
        if (personnelId == null) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<OrgResignApplyDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrgResignApplyDO::getPersonnelId, personnelId);
        wrapper.eq(OrgResignApplyDO::getDeleteEnum, "false");
        wrapper.orderByDesc(OrgResignApplyDO::getApplyTime);
        wrapper.orderByDesc(OrgResignApplyDO::getId);
        return orgResignApplyMapper.selectList(wrapper).stream()
                .map(this::toEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<Long> listPersonnelIdsByAuditStatus(Integer auditStatusCode, Long orgId) {
        if (auditStatusCode == null) {
            return Collections.emptyList();
        }
        Long resolvedOrgId = orgContextResolver.resolveOrgId(orgId);
        LambdaQueryWrapper<OrgResignApplyDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrgResignApplyDO::getDeleteEnum, "false");
        wrapper.eq(OrgResignApplyDO::getAuditStatusCode, auditStatusCode);
        if (resolvedOrgId != null) {
            wrapper.eq(OrgResignApplyDO::getOrgId, resolvedOrgId);
        }
        wrapper.select(OrgResignApplyDO::getPersonnelId);
        return orgResignApplyMapper.selectList(wrapper).stream()
                .map(OrgResignApplyDO::getPersonnelId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
    }

    private OrgResignApplyDO toDO(OrgResignApplyEntity entity) {
        OrgResignApplyDO dataObject = new OrgResignApplyDO();
        dataObject.setOrgId(orgContextResolver.resolveOrgId(entity.getOrgId()));
        dataObject.setPersonnelId(entity.getPersonnelId());
        dataObject.setApplicantName(entity.getApplicantName());
        dataObject.setApplyTime(entity.getApplyTime());
        dataObject.setResignReason(entity.getResignReason());
        dataObject.setExpectedResignDate(entity.getExpectedResignDate());
        dataObject.setReportFileUrl(entity.getReportFileUrl());
        dataObject.setAuditStatusCode(entity.getAuditStatusCode());
        dataObject.setAuditStatusName(entity.getAuditStatusName());
        dataObject.setRejectReason(entity.getRejectReason());
        dataObject.setRemarks(entity.getRemark());
        dataObject.setTenantId(entity.getTenantId());
        return dataObject;
    }

    private OrgResignApplyEntity toEntity(OrgResignApplyDO dataObject) {
        if (dataObject == null) {
            return null;
        }
        OrgResignApplyEntity entity = new OrgResignApplyEntity();
        entity.setId(dataObject.getId());
        entity.setPersonnelId(dataObject.getPersonnelId());
        entity.setApplicantName(dataObject.getApplicantName());
        entity.setApplyTime(dataObject.getApplyTime());
        entity.setResignReason(dataObject.getResignReason());
        entity.setExpectedResignDate(dataObject.getExpectedResignDate());
        entity.setReportFileUrl(dataObject.getReportFileUrl());
        entity.setAuditStatusCode(dataObject.getAuditStatusCode());
        entity.setAuditStatusName(dataObject.getAuditStatusName());
        entity.setRejectReason(dataObject.getRejectReason());
        entity.setRemark(dataObject.getRemarks());
        entity.setTenantId(dataObject.getTenantId());
        return entity;
    }
}
