package cn.com.ty.lift.system.settings.service.impl;

import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.constants.DefaultMenuConstants;
import cn.com.ty.lift.common.utils.PojoUtils;
import cn.com.ty.lift.common.utils.ProjectUtils;
import cn.com.ty.lift.system.constants.CommonConstants;
import cn.com.ty.lift.system.settings.dao.entity.MaintenanceCompany;
import cn.com.ty.lift.system.settings.dao.entity.MtCompanyAttestation;
import cn.com.ty.lift.system.settings.dao.entity.model.CompanyAttestationRequest;
import cn.com.ty.lift.system.settings.dao.entity.model.CompanyAttestationResponse;
import cn.com.ty.lift.system.settings.dao.entity.model.MaintenanceCompanyRequest;
import cn.com.ty.lift.system.settings.dao.entity.model.MaintenanceCompanyResponse;
import cn.com.ty.lift.system.settings.dao.mapper.MtCompanyAttestationMapper;
import cn.com.ty.lift.system.settings.service.GlobalSetService;
import cn.com.ty.lift.system.settings.service.IMaintenanceCompanyService;
import cn.com.ty.lift.system.settings.service.IMtCompanyAttestationService;
import cn.com.ty.lift.system.user.dao.entity.Role;
import cn.com.ty.lift.system.user.dao.entity.UserAccount;
import cn.com.ty.lift.system.user.dao.entity.UserInfo;
import cn.com.ty.lift.system.user.dao.entity.model.ApplyPageResponse;
import cn.com.ty.lift.system.user.dao.entity.model.MenuRequest;
import cn.com.ty.lift.system.user.service.*;
import cn.com.xwy.boot.web.dto.RestResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 公司认证信息 服务实现类
 * </p>
 *
 * @author huangyuan
 * @since 2019-12-12
 */
@Service
public class MtCompanyAttestationServiceImpl extends ServiceImpl<MtCompanyAttestationMapper, MtCompanyAttestation> implements IMtCompanyAttestationService {

    @Resource
    private MtCompanyAttestationMapper mtCompanyAttestationMapper;

    @Resource
    private IMaintenanceCompanyService maintenanceCompanyService;

    @Resource
    private IRoleService roleService;

    @Resource
    private IMenuService menuService;

    @Resource
    private GlobalSetService globalSetService;

    @Resource
    private IUserAccountService userAccountService;

    @Resource
    private IUserInfoService userInfoService;

    @Resource
    private IUserApplicationService userApplicationService;

    @Override
    @Transactional
    public RestResponse applyAudit(CompanyAttestationRequest companyAttestationRequest) {
        UserInfo userInfo = userInfoService.getByUserId(companyAttestationRequest.getUserId());
        MaintenanceCompany maintenanceCompany = maintenanceCompanyService.getById(companyAttestationRequest.getMtCompanyId());
        if (maintenanceCompany == null) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "团队不存在不能发起认证");
        }
        //判断发起认证的人是否是团队创建者
        if (!companyAttestationRequest.getUserId().equals(maintenanceCompany.getCreatorId())) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "当前用户不是团队管理者无法发起认证");
        }
        MtCompanyAttestation mtCompanyAttestation = new MtCompanyAttestation(companyAttestationRequest);
        if (mtCompanyAttestation.getId() != null) {
            //如果用户是重新认证，获取认证对象
            MtCompanyAttestation mtCompanyAttestationInfo = this.getById(mtCompanyAttestation.getId());
            //属性赋值，将前端修改的值赋值给原来的认证对象
            PojoUtils.pojoCopy(mtCompanyAttestationInfo, mtCompanyAttestation);
            mtCompanyAttestation = mtCompanyAttestationInfo;
        } else {
            //如果是申请，判断是否重复申请
            int companyAttestationCount = this.count(new QueryWrapper<MtCompanyAttestation>()
                    .eq("mt_company_id", companyAttestationRequest.getMtCompanyId())
            );
            if (companyAttestationCount > 0) {
                return RestResponse.fail(ApiConstants.RESULT_ERROR, "当前公司已经申请过了请勿重复申请");
            }
            if (userInfo != null) {
                //如果是新建,设置创建者名称
                mtCompanyAttestation.setCreateUser(userInfo.getName());
            }
        }
        //将公司信息设置为审核中状态
        maintenanceCompany.setIsCertificated(ApiConstants.CompanyConstants.MAINTENANCE_WAIT_CERTIFICATE);
        //设置公司审核信息为审核中
        mtCompanyAttestation.setIsCertificated(ApiConstants.CompanyConstants.MAINTENANCE_WAIT_CERTIFICATE);
        if (!maintenanceCompanyService.updateById(maintenanceCompany)) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "更新公司信息失败");
        }
        if (!this.saveOrUpdate(mtCompanyAttestation)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存申请信息失败");
        }
        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "发起认证成功");
    }

    @Override
    @Transactional
    public RestResponse auditPass(CompanyAttestationRequest companyAttestationRequest) {
        MtCompanyAttestation mtCompanyAttestation = this.getById(companyAttestationRequest.getId());
        //获取申请的公司id
        Long companyId = mtCompanyAttestation.getMtCompanyId();

        //认证处理
        MaintenanceCompany maintenanceCompany = auditHandle(mtCompanyAttestation, companyAttestationRequest,
                ApiConstants.CompanyConstants.MAINTENANCE_PASS);
        //1.将认证通过的信息赋值到本来公司信息中
        maintenanceCompany.copyAttestation(mtCompanyAttestation);
        //2.设置企业电梯台量
        maintenanceCompany.setLimitedNum(companyAttestationRequest.getLimitedNum());
        //3.设置用户是否是vip用户
        maintenanceCompany.setVipFlag(companyAttestationRequest.getVipFlag());
        if (!this.updateById(mtCompanyAttestation)) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "操作失败");
        }
        //4.分配角色和菜单
        RestResponse restResponse = assignRoleAndMenu(companyAttestationRequest, companyId);
        if (restResponse != null) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return restResponse;
        }
        //5.生成企业设置数据
        if (!globalSetService.teamInitSetting(companyId)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "操作失败");
        }
        //保存公司消息
        if (!maintenanceCompanyService.updateById(maintenanceCompany)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "操作失败");
        }
        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "操作成功");
    }

    @Override
    @Transactional
    public RestResponse auditFail(CompanyAttestationRequest companyAttestationRequest) {
        MtCompanyAttestation mtCompanyAttestation = this.getById(companyAttestationRequest.getId());
        //认证处理
        MaintenanceCompany maintenanceCompany = auditHandle(mtCompanyAttestation, companyAttestationRequest,
                ApiConstants.CompanyConstants.MAINTENANCE_FAIL);
        this.updateById(mtCompanyAttestation);
        maintenanceCompanyService.updateById(maintenanceCompany);
        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "操作成功");
    }

    @Override
    public RestResponse applyList(CompanyAttestationRequest companyAttestationRequest) {
        //获取不同状态的总和
        List<MtCompanyAttestation> mtCompanyAttestationListResult = this.list(new QueryWrapper<MtCompanyAttestation>()
                .select("is_Certificated")
                //过滤没有发起认证的
                .ne("is_Certificated", ApiConstants.CompanyConstants.MAINTENANCE_NOT_CERTIFICATE)
        );
        //封装申请消息
        ApplyPageResponse applyPageResponse = new ApplyPageResponse();
        packCompanyApplyStatusCount(mtCompanyAttestationListResult, applyPageResponse, companyAttestationRequest.getIsCertificated());

        //封装具体信息
        Long currentUserId = companyAttestationRequest.getCurrentUserId();
        if ((ApiConstants.CompanyConstants.MAINTENANCE_NOT_CERTIFICATE == companyAttestationRequest.getIsCertificated())) {
            //所有管理员都可以查看待审核的信息
            currentUserId = null;
        } else {
            //如果不是待审核的信息，查看用户类型
            if (currentUserId != null) {
                UserAccount currentUser = userAccountService.getByUserId(currentUserId);
                //判断当前用户类型，如用户是管理员或者平台管理员就查看所有申请信息
                if (ApiConstants.UserConstants.TYPE_PLATFORM_ADMIN == currentUser.getType()
                        || ApiConstants.UserConstants.TYPE_SUPER_ADMIN == currentUser.getType()) {
                    currentUserId = null;
                }
            }
        }
        IPage mtCompanyAttestationPage = new Page<>(companyAttestationRequest.getPageNum(), companyAttestationRequest.getPageSize());
        mtCompanyAttestationPage = this.page(mtCompanyAttestationPage, new QueryWrapper<MtCompanyAttestation>()
                .eq(currentUserId != null, "customer_manager_id", currentUserId)
                //通过审核状态筛选申请信息
                .eq("is_certificated", companyAttestationRequest.getIsCertificated())
                .eq(companyAttestationRequest.getQueryCompanyId() != null, "mt_company_id", companyAttestationRequest.getQueryCompanyId())
                .and(StringUtils.isNotBlank(companyAttestationRequest.getQueryCondition()), i -> i
                        .like("contacts_name", companyAttestationRequest.getQueryCondition())
                        .or()
                        .like("contacts_tel", companyAttestationRequest.getQueryCondition())
                )
        );
        List<CompanyAttestationResponse> companyAttestationResponseList = new ArrayList<>();
        List<MtCompanyAttestation> mtCompanyAttestationList = mtCompanyAttestationPage.getRecords();
        if (mtCompanyAttestationList != null && mtCompanyAttestationList.size() > 0) {
            //获取客户经理信息
            List<Long> customerManagerIdList = ProjectUtils.getAttrList(mtCompanyAttestationList,
                    "customerManagerId", null);
            List<UserInfo> userInfoList = (List<UserInfo>) userInfoService.listByIds(customerManagerIdList);
            Map<Long, UserInfo> customerManagerIdToUserInfo = ProjectUtils.attrToObjMap(userInfoList,
                    "userId", null);
            //获取公司信息
            List<Long> companyIdList = ProjectUtils.getAttrList(mtCompanyAttestationList,
                    "mtCompanyId", null);
            List<MaintenanceCompany> maintenanceCompanyList = (List<MaintenanceCompany>)
                    maintenanceCompanyService.listByIds(companyIdList);
            Map<Long, MaintenanceCompany> companyIdToMaintenanceCompany = ProjectUtils.attrToObjMap(maintenanceCompanyList, "id", null);
            for (MtCompanyAttestation mtCompanyAttestation : mtCompanyAttestationList) {
                CompanyAttestationResponse companyAttestationResponse = new CompanyAttestationResponse(mtCompanyAttestation);
                //设置客户经理名称
                UserInfo userInfo = customerManagerIdToUserInfo.get(mtCompanyAttestation.getCustomerManagerId());
                if (userInfo != null) {
                    companyAttestationResponse.setCustomerManagerName(userInfo.getName());
                }
                //设置公司信息
                MaintenanceCompany maintenanceCompany = companyIdToMaintenanceCompany.get(mtCompanyAttestation.getMtCompanyId());
                if (maintenanceCompany != null) {
                    companyAttestationResponse.setMtCompanyId(maintenanceCompany.getId());
                    //是否vip
                    Integer vipFlag = maintenanceCompany.getVipFlag() != null ? maintenanceCompany.getVipFlag() : 0;
                    //电梯台量
                    Integer limitedNum = maintenanceCompany.getLimitedNum() != null ? maintenanceCompany.getLimitedNum() : 0;
                    companyAttestationResponse.setVipFlag(vipFlag);
                    companyAttestationResponse.setLimitedNum(limitedNum);
                }
                companyAttestationResponseList.add(companyAttestationResponse);
            }
            mtCompanyAttestationPage.setRecords(companyAttestationResponseList);
        }
        applyPageResponse.setPage(mtCompanyAttestationPage);
        return RestResponse.success(applyPageResponse, ApiConstants.RESULT_SUCCESS, "获取公司申请信息成功");
    }

    @Override
    public RestResponse getAuditResult(CompanyAttestationRequest companyAttestationRequest) {
        //获取团队审核信息
        MtCompanyAttestation mtCompanyAttestation = this.getOne(new QueryWrapper<MtCompanyAttestation>()
                .eq("mt_company_id", companyAttestationRequest.getMtCompanyId())
        );
        return RestResponse.success(mtCompanyAttestation, ApiConstants.RESULT_SUCCESS, "获取申请信息成功");
    }

    @Override
    public Map<Long, LocalDateTime> getMtCompanyIdToDealTime(List<Long> companyIdList) {
        //获取公司认证信息
        List<MtCompanyAttestation> mtCompanyAttestationList = list(new QueryWrapper<MtCompanyAttestation>()
                .select("deal_time")
                .in("mt_company_id", companyIdList)
        );
        //将信息封装为 mtCompanyId(公司id) -> dealTime(处理时间)
        Map<Long, LocalDateTime> companyIdToDealTime = new HashMap<>();
        if (mtCompanyAttestationList != null && mtCompanyAttestationList.size() > 0) {
            mtCompanyAttestationList.forEach(mtCompanyAttestation -> {
                companyIdToDealTime.put(mtCompanyAttestation.getMtCompanyId(), mtCompanyAttestation.getDealTime());
            });
        }
        return companyIdToDealTime;
    }

    @Override
    public RestResponse applyCompanyList(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        List<MaintenanceCompanyResponse> maintenanceCompanyResponseList = mtCompanyAttestationMapper
                .applyCompanyList(maintenanceCompanyRequest.getIsCertificated());
        return RestResponse.success(maintenanceCompanyResponseList, ApiConstants.RESULT_SUCCESS, "获取成功");
    }

    /**
     * @param
     * @return
     * @description 封装企业申请消息对应条数
     * @date 2020-01-06 23:17
     */
    private void packCompanyApplyStatusCount(List<MtCompanyAttestation> mtCompanyAttestationListResult,
                                             ApplyPageResponse applyPageResponse, int isCertificated) {
        Map<Integer, Long> statusToCount = userApplicationService.getApplyStatusToCountMap(mtCompanyAttestationListResult,
                CommonConstants.COMPANY_ATTESTATION_STATUS, "isCertificated");
        //待审核
        applyPageResponse.setApplyWaitCount(statusToCount.get(ApiConstants.CompanyConstants.MAINTENANCE_WAIT_CERTIFICATE));
        //审核通过
        applyPageResponse.setApplyPassCount(statusToCount.get(ApiConstants.CompanyConstants.MAINTENANCE_PASS));
        //审核未通过
        applyPageResponse.setApplyFailCount(statusToCount.get(ApiConstants.CompanyConstants.MAINTENANCE_FAIL));
        //当前状态为筛选条数
        Long count = statusToCount.get(isCertificated) == null ? 0L : statusToCount.get(isCertificated);
        applyPageResponse.setCount(count);
    }

    /***
     * @description
     * @date 2019-12-13 09:32
     * @param mtCompanyAttestation 公司认证对象
     * @param companyAttestationRequest 公司认证请求对象
     * @param auditResult 审核结果
     * @return
     */
    private MaintenanceCompany auditHandle(MtCompanyAttestation mtCompanyAttestation,
                                           CompanyAttestationRequest companyAttestationRequest, int auditResult) {
        MaintenanceCompany maintenanceCompany = maintenanceCompanyService.getById(mtCompanyAttestation.getMtCompanyId());
        //设置认证时间
        mtCompanyAttestation.setDealTime(LocalDateTime.now());
        //设置认证理由
        mtCompanyAttestation.setCheckFeedBack(companyAttestationRequest.getCheckFeedBack());
        //设置客服经理
        mtCompanyAttestation.setCustomerManagerId(companyAttestationRequest.getCustomerManagerId());
        //设置认证结果
        mtCompanyAttestation.setIsCertificated(auditResult);
        //设置认证结果
        maintenanceCompany.setIsCertificated(auditResult);
        return maintenanceCompany;
    }

    /**
     * @param companyAttestationRequest 请求信息
     * @param companyId                 公司id
     * @description 分配菜单和角色
     * @date 2020/4/26 10:57 上午
     */
    private RestResponse assignRoleAndMenu(CompanyAttestationRequest companyAttestationRequest, Long companyId) {
        int defaultAssign = companyAttestationRequest.getDefaultAssign();
        //1.分配默认角色
        List<Role> defaultRoleList = new ArrayList<>();
        for (CommonEnum.DefaultRole defaultRole : DefaultMenuConstants.DEFAULT_ROLE) {
            Role newRole = new Role(defaultRole);
            newRole.setCompanyId(companyId);
            newRole.setDescription(defaultRole.getLabel());
            defaultRoleList.add(newRole);
        }
        if (!roleService.saveBatch(defaultRoleList)) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "操作失败-分配默认角色失败");
        }

        //2.给企业分配菜单
        String menuIds = companyAttestationRequest.getMenuIds();
        if (1 == defaultAssign) {
            menuIds = ProjectUtils.arrayToStrByComma(DefaultMenuConstants.ENTERPRISE_MENUIDS);
        }
        RestResponse restResponse = menuService.companyMenu(new MenuRequest(companyId, menuIds));
        if (restResponse != null) {
            return restResponse;
        }
        //3.设置企业管理员菜单
        //获取当前企业的企业管理员
        Role enterpriseAdminRole = roleService.getOne(new QueryWrapper<Role>()
                .eq("company_id", companyId)
                .eq("code", CommonEnum.DefaultRole.ENTERPRISE_ADMIN.getCode()));
        if (enterpriseAdminRole == null) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "企业管理员不存在，无法通过审核");
        }
        long[] enterpriseMenuIds = ProjectUtils.getLongIdArrayFromIds(menuIds);
        DefaultMenuConstants.DEFAULT_ROLE_MENUIDS.put(CommonEnum.DefaultRole.ENTERPRISE_ADMIN.getCode(),
                enterpriseMenuIds);
        //4.角色菜单分配
        if (!roleService.assignDefaultMenu(defaultAssign, defaultRoleList, enterpriseAdminRole)) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "分配默认角色菜单失败");
        }
        return null;
    }

}
