package org.qinan.safetyeval.app.executor;

import com.jjb.saas.system.client.user.facade.UserFacade;
import com.jjb.saas.system.client.user.request.FacadeUserAddCmd;
import com.jjb.saas.system.client.user.request.UserAddCmd;
import com.jjb.saas.system.client.user.request.UserUpdatePasswordCmd;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zcloud.gbscommon.utils.MD5;
import com.zcloud.gbscommon.utils.Sm2Util;
import org.apache.dubbo.config.annotation.DubboReference;
import org.qinan.safetyeval.app.support.OrgPersonnelChangeRecorder;
import org.qinan.safetyeval.app.support.OrgPersonnelViewEnricher;
import org.qinan.safetyeval.client.api.OrgPersonnelApi;
import org.qinan.safetyeval.client.co.OrgPersonnelCO;
import org.qinan.safetyeval.client.dto.OrgPersonnelAddCmd;
import org.qinan.safetyeval.client.dto.OrgPersonnelModifyCmd;
import org.qinan.safetyeval.client.dto.OrgPersonnelPageQuery;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.domain.entity.OrgPersonnelEntity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.gateway.OrgResignApplyGateway;
import org.qinan.safetyeval.domain.query.OrgPersonnelQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.service.OrgPersonnelDomainService;
import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter;
import org.qinan.safetyeval.infrastructure.adapter.gbs.GbsUserFacadeClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 人员信息执行器（App层）
 */
@Service
public class OrgPersonnelExecutor implements OrgPersonnelApi {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrgPersonnelExecutor.class);

    @Lazy
    @Autowired(required = false)
    private OrgPersonnelDomainService orgPersonnelDomainService;

    @Autowired(required = false)
    private OrgPersonnelViewEnricher orgPersonnelViewEnricher;

    @Autowired(required = false)
    private OrgPersonnelChangeRecorder orgPersonnelChangeRecorder;

    @Autowired(required = false)
    private OrgResignApplyGateway orgResignApplyGateway;

    @Autowired
    private GbsUserFacadeClient gbsUserFacadeClient;

    @Value("${def.password:a123456}")
    private String defPassword;
    @Value("${def.publicKey:0402df2195296d4062ac85ad766994d73e871b887e18efb9a9a06b4cebc72372869b7da6c347c129dee2b46a0f279ff066b01c76208c2a052af75977c722a2ccee}")
    private String publicKey;


    @Value("${safety-eval.gbs-user-sync.fail-fast:true}")
    private boolean gbsUserSyncFailFast;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<OrgPersonnelCO> add(OrgPersonnelAddCmd cmd) {
        OrgPersonnelEntity entity = toEntity(cmd);
        OrgPersonnelEntity result = orgPersonnelDomainService.add(entity);
        OrgPersonnelCO co = toCO(result);
        enrich(co);
        UserAddCmd userAddCmd = new UserAddCmd();
        userAddCmd.setId(result.getId());
        userAddCmd.setAccount(result.getAccount());
        userAddCmd.setIdCard(result.getIdCardNo());
        userAddCmd.setTenantId(result.getTenantId());
        userAddCmd.setName(result.getUserName());
        String encrypt = Sm2Util.encryptHex(MD5.md5(defPassword), publicKey);
        userAddCmd.setPassword(encrypt);
        gbsUserFacadeClient.add(userAddCmd);
        return SingleResponse.success(co);
    }

    @Override
    public SingleResponse<OrgPersonnelCO> get(Long id) {
        OrgPersonnelEntity entity = orgPersonnelDomainService.get(id);
        OrgPersonnelCO co = toCO(entity);
        enrich(co);
        return SingleResponse.success(co);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<OrgPersonnelCO> modify(OrgPersonnelModifyCmd cmd) {
        OrgPersonnelEntity existing = orgPersonnelDomainService.get(cmd.getId());
        OrgPersonnelEntity entity = toEntity(cmd);
        entity.setId(cmd.getId());
        OrgPersonnelEntity result = orgPersonnelDomainService.modify(entity);
        orgPersonnelChangeRecorder.recordChanges(existing, result);
        OrgPersonnelCO co = toCO(result);
        enrich(co);
        return SingleResponse.success(co);
    }

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

    @Override
    public SingleResponse<Void> resetPassword(Long id) {
        OrgPersonnelEntity entity = orgPersonnelDomainService.get(id);
        if (entity == null) {
            throw new BizException(ErrorCode.ORG_PERSONNEL_NOT_FOUND);
        }
        // 联调阶段：密码重置占位，后续对接统一用户中心
        UserUpdatePasswordCmd userUpdatePasswordCmd = new UserUpdatePasswordCmd();
        userUpdatePasswordCmd.setId(entity.getId());
        String encrypt = Sm2Util.encryptHex(MD5.md5(defPassword), publicKey);
        userUpdatePasswordCmd.setPassword(encrypt);
        gbsUserFacadeClient.updatePassword(userUpdatePasswordCmd);
        return SingleResponse.success();
    }

    @Override
    public PageResponse<OrgPersonnelCO> page(OrgPersonnelPageQuery query) {
        OrgPersonnelQuery domainQuery = new OrgPersonnelQuery();
        domainQuery.setPageNum(query.getCurrent());
        domainQuery.setPageSize(query.getSize());
        domainQuery.setTenantId(AuthUserContextAdapter.getCurrentTenantId());
        domainQuery.setOrgId(query.getOrgId());
        domainQuery.setDeptId(query.getDeptId());
        domainQuery.setPostId(query.getPostId());
        domainQuery.setUserName(query.getUserName());
        domainQuery.setAccount(query.getAccount());
        domainQuery.setEmploymentStatusCode(query.getEmploymentStatusCode());
        if (query.getResignAuditStatus() != null && orgResignApplyGateway != null) {
            domainQuery.setPersonnelIds(orgResignApplyGateway.listPersonnelIdsByAuditStatus(
                    query.getResignAuditStatus(), query.getOrgId()));
        }

        PageResult<OrgPersonnelEntity> pageResult = orgPersonnelDomainService.page(domainQuery);

        List<OrgPersonnelCO> records = pageResult.getRecords().stream()
                .map(entity -> {
                    OrgPersonnelCO co = toCO(entity);
                    enrich(co);
                    return co;
                })
                .collect(java.util.stream.Collectors.toList());

        return PageResponse.of(records, pageResult.getTotal());
    }

    private void syncGbsUser(String action, Runnable runnable) {
        try {
            runnable.run();
        } catch (RuntimeException ex) {
            LOGGER.warn("GBS user sync failed while {}", action, ex);
            if (gbsUserSyncFailFast) {
                throw ex;
            }
        }
    }
    private void enrich(OrgPersonnelCO co) {
        if (orgPersonnelViewEnricher != null) {
            orgPersonnelViewEnricher.enrichPersonnel(co);
        }
    }

    private OrgPersonnelEntity toEntity(OrgPersonnelAddCmd cmd) {
        OrgPersonnelEntity entity = new OrgPersonnelEntity();
        entity.setUserName(cmd.getUserName());
        entity.setAccount(cmd.getAccount());
        entity.setGenderCode(cmd.getGenderCode());
        entity.setGenderName(cmd.getGenderName());
        entity.setBirthDate(cmd.getBirthDate());
        entity.setIdCardNo(cmd.getIdCardNo());
        entity.setCurrentAddress(cmd.getCurrentAddress());
        entity.setOfficeAddress(cmd.getOfficeAddress());
        entity.setEducationCode(cmd.getEducationCode());
        entity.setEducationName(cmd.getEducationName());
        entity.setGraduateSchool(cmd.getGraduateSchool());
        entity.setMajor(cmd.getMajor());
        entity.setEmploymentStatusCode(cmd.getEmploymentStatusCode());
        entity.setEmploymentStatusName(cmd.getEmploymentStatusName());
        applyPersonnelExtFields(entity, cmd);
        entity.setDeptId(cmd.getDeptId());
        entity.setPostId(cmd.getPostId());
        return entity;
    }

    private OrgPersonnelEntity toEntity(OrgPersonnelModifyCmd cmd) {
        OrgPersonnelEntity entity = new OrgPersonnelEntity();
        entity.setUserName(cmd.getUserName());
        entity.setAccount(cmd.getAccount());
        entity.setGenderCode(cmd.getGenderCode());
        entity.setGenderName(cmd.getGenderName());
        entity.setBirthDate(cmd.getBirthDate());
        entity.setIdCardNo(cmd.getIdCardNo());
        entity.setCurrentAddress(cmd.getCurrentAddress());
        entity.setOfficeAddress(cmd.getOfficeAddress());
        entity.setEducationCode(cmd.getEducationCode());
        entity.setEducationName(cmd.getEducationName());
        entity.setGraduateSchool(cmd.getGraduateSchool());
        entity.setMajor(cmd.getMajor());
        entity.setEmploymentStatusCode(cmd.getEmploymentStatusCode());
        entity.setEmploymentStatusName(cmd.getEmploymentStatusName());
        applyPersonnelExtFields(entity, cmd);
        entity.setDeptId(cmd.getDeptId());
        entity.setPostId(cmd.getPostId());
        return entity;
    }

    private void applyPersonnelExtFields(OrgPersonnelEntity entity, OrgPersonnelAddCmd cmd) {
        entity.setPersonTypeCode(cmd.getPersonTypeCode());
        entity.setPersonTypeName(cmd.getPersonTypeName());
        entity.setQualScope(cmd.getQualScope());
        entity.setProfessionalLevelCode(cmd.getProfessionalLevelCode());
        entity.setProfessionalLevelName(cmd.getProfessionalLevelName());
        entity.setEvaluatorCertNo(cmd.getEvaluatorCertNo());
        entity.setEducationTypeCode(cmd.getEducationTypeCode());
        entity.setEducationTypeName(cmd.getEducationTypeName());
        entity.setEducationLevelCode(cmd.getEducationLevelCode());
        entity.setEducationLevelName(cmd.getEducationLevelName());
        entity.setTitleName(cmd.getTitleName());
        entity.setRegisterEngineerFlag(cmd.getRegisterEngineerFlag());
        entity.setPublications(cmd.getPublications());
        entity.setAbilityDeclaration(cmd.getAbilityDeclaration());
        entity.setWorkExperience(cmd.getWorkExperience());
        entity.setProofMaterialUrl(cmd.getProofMaterialUrl());
    }

    private void applyPersonnelExtFields(OrgPersonnelEntity entity, OrgPersonnelModifyCmd cmd) {
        entity.setPersonTypeCode(cmd.getPersonTypeCode());
        entity.setPersonTypeName(cmd.getPersonTypeName());
        entity.setQualScope(cmd.getQualScope());
        entity.setProfessionalLevelCode(cmd.getProfessionalLevelCode());
        entity.setProfessionalLevelName(cmd.getProfessionalLevelName());
        entity.setEvaluatorCertNo(cmd.getEvaluatorCertNo());
        entity.setEducationTypeCode(cmd.getEducationTypeCode());
        entity.setEducationTypeName(cmd.getEducationTypeName());
        entity.setEducationLevelCode(cmd.getEducationLevelCode());
        entity.setEducationLevelName(cmd.getEducationLevelName());
        entity.setTitleName(cmd.getTitleName());
        entity.setRegisterEngineerFlag(cmd.getRegisterEngineerFlag());
        entity.setPublications(cmd.getPublications());
        entity.setAbilityDeclaration(cmd.getAbilityDeclaration());
        entity.setWorkExperience(cmd.getWorkExperience());
        entity.setProofMaterialUrl(cmd.getProofMaterialUrl());
    }

    private OrgPersonnelCO toCO(OrgPersonnelEntity entity) {
        if (entity == null) {
            return null;
        }
        OrgPersonnelCO co = new OrgPersonnelCO();
        co.setId(entity.getId());
        co.setDeptId(entity.getDeptId());
        co.setPostId(entity.getPostId());
        co.setUserName(entity.getUserName());
        co.setAccount(entity.getAccount());
        co.setGenderCode(entity.getGenderCode());
        co.setGenderName(entity.getGenderName());
        co.setBirthDate(entity.getBirthDate());
        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.setEmploymentStatusCode(entity.getEmploymentStatusCode());
        co.setEmploymentStatusName(entity.getEmploymentStatusName());
        co.setPersonTypeCode(entity.getPersonTypeCode());
        co.setPersonTypeName(entity.getPersonTypeName());
        co.setQualScope(entity.getQualScope());
        co.setProfessionalLevelCode(entity.getProfessionalLevelCode());
        co.setProfessionalLevelName(entity.getProfessionalLevelName());
        co.setEvaluatorCertNo(entity.getEvaluatorCertNo());
        co.setEducationTypeCode(entity.getEducationTypeCode());
        co.setEducationTypeName(entity.getEducationTypeName());
        co.setEducationLevelCode(entity.getEducationLevelCode());
        co.setEducationLevelName(entity.getEducationLevelName());
        co.setTitleName(entity.getTitleName());
        co.setRegisterEngineerFlag(entity.getRegisterEngineerFlag());
        co.setPublications(entity.getPublications());
        co.setAbilityDeclaration(entity.getAbilityDeclaration());
        co.setWorkExperience(entity.getWorkExperience());
        co.setProofMaterialUrl(entity.getProofMaterialUrl());
        co.setTenantId(entity.getTenantId());
        return co;
    }
}
