package org.qinan.safetyeval.app.executor;

import org.qinan.safetyeval.client.api.OrgResignApplyApi;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.co.OrgResignApplyCO;
import org.qinan.safetyeval.client.dto.OrgResignApplyAddCmd;
import org.qinan.safetyeval.client.dto.OrgResignApplyModifyCmd;
import org.qinan.safetyeval.client.dto.OrgResignApplyPageQuery;
import org.qinan.safetyeval.domain.entity.OrgResignApplyEntity;
import org.qinan.safetyeval.domain.entity.OrgPersonnelEntity;
import org.qinan.safetyeval.domain.gateway.OrgPersonnelGateway;
import org.qinan.safetyeval.domain.query.OrgResignApplyQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.service.OrgResignApplyDomainService;
import org.qinan.safetyeval.app.support.OrgPersonnelViewEnricher;
import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * 人员离职申请执行器（App层）
 *
 * @author safety-eval
 */
@Service
public class OrgResignApplyExecutor implements OrgResignApplyApi {

    @Lazy
    @Autowired(required = false)
    private OrgResignApplyDomainService orgResignApplyDomainService;

    @Autowired(required = false)
    private OrgPersonnelViewEnricher orgPersonnelViewEnricher;

    @Autowired(required = false)
    private OrgPersonnelGateway orgPersonnelGateway;

    @Override
    public SingleResponse<OrgResignApplyCO> add(OrgResignApplyAddCmd cmd) {
        OrgResignApplyEntity entity = new OrgResignApplyEntity();
        Long personnelId = resolvePersonnelId(cmd.getPersonnelId(), cmd.getApplicantName());
        entity.setPersonnelId(personnelId);
        entity.setApplicantName(resolveApplicantName(personnelId, cmd.getApplicantName()));
        entity.setApplyTime(cmd.getApplyTime());
        entity.setResignReason(cmd.getResignReason());
        entity.setExpectedResignDate(cmd.getExpectedResignDate());
        entity.setReportFileUrl(cmd.getReportFileUrl());
        entity.setAuditStatusCode(cmd.getAuditStatusCode() != null ? cmd.getAuditStatusCode() : 0);
        entity.setAuditStatusName(cmd.getAuditStatusName() != null ? cmd.getAuditStatusName() : "未审核");
        entity.setRejectReason(cmd.getRejectReason());
        entity.setRemark(cmd.getRemark());

        OrgResignApplyEntity result = orgResignApplyDomainService.add(entity);
        OrgResignApplyCO co = toCO(result);
        enrich(co);
        return SingleResponse.success(co);
    }

    @Override
    public SingleResponse<OrgResignApplyCO> get(Long id) {
        OrgResignApplyEntity entity = orgResignApplyDomainService.get(id);
        OrgResignApplyCO co = toCO(entity);
        enrich(co);
        return SingleResponse.success(co);
    }

    @Override
    public SingleResponse<OrgResignApplyCO> modify(OrgResignApplyModifyCmd cmd) {
        OrgResignApplyEntity entity = new OrgResignApplyEntity();
        entity.setId(cmd.getId());
        entity.setApplicantName(cmd.getApplicantName());
        entity.setApplyTime(cmd.getApplyTime());
        entity.setResignReason(cmd.getResignReason());
        entity.setExpectedResignDate(cmd.getExpectedResignDate());
        entity.setReportFileUrl(cmd.getReportFileUrl());
        entity.setAuditStatusCode(cmd.getAuditStatusCode());
        entity.setAuditStatusName(cmd.getAuditStatusName());
        entity.setRejectReason(cmd.getRejectReason());
        entity.setRemark(cmd.getRemark());
        entity.setPersonnelId(cmd.getPersonnelId());

        if (entity.getAuditStatusCode() != null && entity.getAuditStatusName() == null) {
            entity.setAuditStatusName(resolveAuditStatusName(entity.getAuditStatusCode()));
        }

        OrgResignApplyEntity result = orgResignApplyDomainService.modify(entity);
        syncPersonnelEmploymentAfterAudit(result);
        OrgResignApplyCO co = toCO(result);
        enrich(co);
        return SingleResponse.success(co);
    }

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

    @Override
    public PageResponse<OrgResignApplyCO> page(OrgResignApplyPageQuery query) {
        OrgResignApplyQuery domainQuery = new OrgResignApplyQuery();
        domainQuery.setPageNum(query.getCurrent());
        domainQuery.setPageSize(query.getSize());
        domainQuery.setTenantId(AuthUserContextAdapter.getCurrentTenantId());
        domainQuery.setOrgId(query.getOrgId());
        domainQuery.setPersonnelId(query.getPersonnelId());
        domainQuery.setAuditStatusCode(query.getAuditStatusCode());
        domainQuery.setApplicantName(query.getApplicantName());

        PageResult<OrgResignApplyEntity> pageResult = orgResignApplyDomainService.page(domainQuery);

        return PageResponse.of(
                pageResult.getRecords().stream()
                        .map(entity -> {
                            OrgResignApplyCO co = toCO(entity);
                            enrich(co);
                            return co;
                        })
                        .collect(java.util.stream.Collectors.toList()),
                pageResult.getTotal());
    }

    private void enrich(OrgResignApplyCO co) {
        if (orgPersonnelViewEnricher != null) {
            orgPersonnelViewEnricher.enrichResignApply(co);
        }
    }

    private String resolveApplicantName(Long personnelId, String applicantName) {
        if (personnelId != null && orgPersonnelGateway != null) {
            OrgPersonnelEntity personnel = orgPersonnelGateway.get(personnelId);
            if (personnel != null && StringUtils.hasText(personnel.getUserName())) {
                return personnel.getUserName();
            }
        }
        if (StringUtils.hasText(applicantName)) {
            return applicantName;
        }
        String currentUserName = AuthUserContextAdapter.getCurrentUserName();
        return StringUtils.hasText(currentUserName) ? currentUserName : applicantName;
    }

    private Long resolvePersonnelId(Long personnelId, String applicantName) {
        if (personnelId != null) {
            return personnelId;
        }
        if (orgPersonnelGateway == null || !StringUtils.hasText(applicantName)) {
            return null;
        }
        OrgPersonnelEntity personnel = orgPersonnelGateway.findByUserName(applicantName);
        if (personnel == null) {
            personnel = orgPersonnelGateway.getByAccount(applicantName);
        }
        return personnel != null ? personnel.getId() : null;
    }

    private void syncPersonnelEmploymentAfterAudit(OrgResignApplyEntity result) {
        if (result == null || result.getPersonnelId() == null || orgPersonnelGateway == null) {
            return;
        }
        if (result.getAuditStatusCode() == null || result.getAuditStatusCode() != 1) {
            return;
        }
        OrgPersonnelEntity personnel = orgPersonnelGateway.get(result.getPersonnelId());
        if (personnel == null) {
            return;
        }
        personnel.setEmploymentStatusCode(2);
        personnel.setEmploymentStatusName("离职");
        orgPersonnelGateway.modify(personnel);
    }

    private String resolveAuditStatusName(Integer auditStatusCode) {
        if (auditStatusCode == null) {
            return "未审核";
        }
        if (auditStatusCode == 1) {
            return "已审核";
        }
        if (auditStatusCode == 2) {
            return "已退回";
        }
        return "未审核";
    }

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