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.utils.ProjectUtils;
import cn.com.ty.lift.system.homepage.dao.dto.request.LiftDataRequest;
import cn.com.ty.lift.system.homepage.dao.dto.response.LiftDataResponse;
import cn.com.ty.lift.system.homepage.dao.mapper.CommonDataMapper;
import cn.com.ty.lift.system.homepage.dao.mapper.HomeLiftDataMapper;
import cn.com.ty.lift.system.homepage.dao.model.CountDataModel;
import cn.com.ty.lift.system.homepage.dao.model.LiftMapDataModel;
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.ConfirmCompanyResponse;
import cn.com.ty.lift.system.settings.dao.entity.model.MaintenanceCompanyRequest;
import cn.com.ty.lift.system.settings.dao.entity.model.TeamInfoResponse;
import cn.com.ty.lift.system.settings.dao.mapper.MaintenanceCompanyMapper;
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.MtCompanyUser;
import cn.com.ty.lift.system.user.dao.entity.Role;
import cn.com.ty.lift.system.user.dao.entity.UserRole;
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.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 维保公司 服务实现类
 * </p>
 *
 * @author huangyuan
 * @since 2019-12-09
 */
@Service
public class MaintenanceCompanyServiceImpl extends ServiceImpl<MaintenanceCompanyMapper, MaintenanceCompany> implements IMaintenanceCompanyService {

    @Resource
    private IRoleService roleService;

    @Resource
    private IUserRoleService userRoleService;

    @Resource
    private IMenuService menuService;

    @Resource
    private IUserAccountService userAccountService;

    @Resource
    private IMtCompanyUserService mtCompanyUserService;

    @Resource
    private IMtCompanyAttestationService mtCompanyAttestationService;

    @Resource
    private CommonDataMapper commonDataMapper;

    @Resource
    private HomeLiftDataMapper homeLiftDataMapper;

    @Override
    public RestResponse list(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        IPage<MaintenanceCompany> maintenanceCompanyPage = new Page<>(
                maintenanceCompanyRequest.getPageNum(), maintenanceCompanyRequest.getPageSize());
        maintenanceCompanyPage = this.page(
                maintenanceCompanyPage, new QueryWrapper<MaintenanceCompany>()
                        //通过公司名称模糊查找公司信息
                        .like(StringUtils.isNotBlank(maintenanceCompanyRequest.getCompanyName()), "name",
                                maintenanceCompanyRequest.getCompanyName())
        );
        //设置维保公司人数
        setCompanyUserNum(maintenanceCompanyPage.getRecords());
        return RestResponse.success(maintenanceCompanyPage, ApiConstants.RESULT_SUCCESS, "获取公司列表成功");
    }

    @Override
    @Transactional
    public RestResponse createTeam(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        MaintenanceCompany maintenanceCompany = new MaintenanceCompany();
        //当前登录用户id
        Long userId = maintenanceCompanyRequest.getUserId();
        //设置申请团队信息
        maintenanceCompany.setName(maintenanceCompanyRequest.getCompanyName());
        maintenanceCompany.setCorporator(maintenanceCompanyRequest.getCorporator());
        maintenanceCompany.setCreatorId(userId);
        maintenanceCompany.setTelephone(maintenanceCompanyRequest.getTelephone());
        //设置团队状态为未认证
        maintenanceCompany.setIsCertificated(ApiConstants.CompanyConstants.MAINTENANCE_NOT_CERTIFICATE);
        maintenanceCompany.setRemarks(maintenanceCompanyRequest.getRemarks());
        maintenanceCompany.setLogoImg(maintenanceCompanyRequest.getLogoImg());
        maintenanceCompany.setCreateDate(LocalDateTime.now());
        if (!this.save(maintenanceCompany)) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存团队信息失败");
        }
        //公司id
        Long companyId = maintenanceCompany.getId();

        //创建团队成功
        MtCompanyUser mtCompanyUser = new MtCompanyUser();
        mtCompanyUser.setCreateUserId(userId);
        mtCompanyUser.setUserId(userId);
        mtCompanyUser.setStatus(ApiConstants.ApplicationConstants.APPLY_PASS);
        mtCompanyUser.setMtCompanyId(companyId);
        if (!mtCompanyUserService.save(mtCompanyUser)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存成员关联公司信息失败");
        }
        //2.创建默认角色-企业管理员
        Role role = new Role();
        role.setName(CommonEnum.DefaultRole.ENTERPRISE_ADMIN.getLabel());
        role.setCode(CommonEnum.DefaultRole.ENTERPRISE_ADMIN.getCode());
        role.setCompanyId(companyId);
        role.setDescription("企业管理员");
        if (!roleService.save(role)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存角色信息失败");
        }
        //3.创建用户角色关联关系
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRole.setRoleId(role.getId());
        userRole.setCompanyId(companyId);
        if (!userRoleService.save(userRole)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存创建者和角色关联关系失败");
        }

        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "创建团队成功");
    }

    @Override
    @Transactional
    public RestResponse updateMaintenanceCompany(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        //获取申请消息
        MtCompanyAttestation mtCompanyAttestation = mtCompanyAttestationService.getById(maintenanceCompanyRequest.getId());
        //获取公司id
        Long companyId = mtCompanyAttestation.getMtCompanyId();
        MaintenanceCompany maintenanceCompany = this.getById(companyId);
        //更新vip标识
        maintenanceCompany.setVipFlag(maintenanceCompanyRequest.getVipFlag());
        //更新电梯台量
        maintenanceCompany.setLimitedNum(maintenanceCompanyRequest.getLimitedNum());
        //更新企业菜单信息
        menuService.companyMenu(new MenuRequest(companyId, maintenanceCompanyRequest.getMenuIds()));
        this.updateById(maintenanceCompany);
        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "更新公司信息成功");
    }

    @Override
    public RestResponse ownList(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        //获取关联关系
        List<MtCompanyUser> mtCompanyUserList = mtCompanyUserService.list(new QueryWrapper<MtCompanyUser>()
                .eq("user_id", maintenanceCompanyRequest.getUserId())
                .eq("status", ApiConstants.ApplicationConstants.APPLY_PASS)
        );
        //获取所在的团队信息
        if (mtCompanyUserList != null && mtCompanyUserList.size() > 0) {
            List<Long> companyIdList = ProjectUtils.getAttrList(mtCompanyUserList, "mtCompanyId", null);
            List<MaintenanceCompany> maintenanceCompanyList = (List<MaintenanceCompany>) this.listByIds(companyIdList);
            //设置维保公司人数
            setCompanyUserNum(maintenanceCompanyList);
            for (MaintenanceCompany maintenanceCompany : maintenanceCompanyList) {
                if (maintenanceCompany.getId().equals(maintenanceCompanyRequest.getCompanyId())) {
                    maintenanceCompany.setCurrentTeamFlag(true);
                }
            }
            return RestResponse.success(maintenanceCompanyList, ApiConstants.RESULT_SUCCESS, "获取用户所在团队列表成功");
        }
        return RestResponse.success(null, ApiConstants.RESULT_NO_DATA, "用户还未加入任何团队");
    }

    @Override
    public void setCompanyUserNum(List<MaintenanceCompany> maintenanceCompanyList) {
        if (maintenanceCompanyList != null && maintenanceCompanyList.size() > 0) {
            List<Long> companyId = ProjectUtils.getAttrList(maintenanceCompanyList, "id", null);
            //获取公司成员信息
            List<MtCompanyUser> mtCompanyUserList = mtCompanyUserService.list(new QueryWrapper<MtCompanyUser>()
                    .select("mt_company_id")
                    .in("mt_company_id", companyId)
            );
            Map<Long, List<MtCompanyUser>> companyIdToMtCompanyUser = ProjectUtils.attrToListMap(mtCompanyUserList, "mtCompanyId", null);
            //循环设置公司人数
            for (MaintenanceCompany maintenanceCompany : maintenanceCompanyList) {
                List<MtCompanyUser> mtCompanyUsers = companyIdToMtCompanyUser.get(maintenanceCompany.getId());
                maintenanceCompany.setUserNum(0);
                if (mtCompanyUsers != null) {
                    maintenanceCompany.setUserNum(mtCompanyUsers.size());
                }
            }
        }
    }

    @Override
    public RestResponse getConfirmCompanyList(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        List<ConfirmCompanyResponse> confirmCompanyResponseList = new ArrayList<>();
        //分页数据
        IPage maintenanceCompanyPage = new Page<>(maintenanceCompanyRequest.getPageNum(),
                maintenanceCompanyRequest.getPageSize());
        //获取已认证的团队信息
        maintenanceCompanyPage = page(maintenanceCompanyPage, new QueryWrapper<MaintenanceCompany>()
                //如果省份信息
                .eq(StringUtils.isNotBlank(maintenanceCompanyRequest.getProvinceCode()), "province_code",
                        maintenanceCompanyRequest.getProvinceCode())
                .eq(maintenanceCompanyRequest.getVipFlag() != null, "vip_flag",
                        maintenanceCompanyRequest.getVipFlag())
                .eq("is_certificated", ApiConstants.CompanyConstants.MAINTENANCE_PASS)
        );
        List<MaintenanceCompany> maintenanceCompanyList = maintenanceCompanyPage.getRecords();
        //封装认证企业信息
        packConfirmCompany(maintenanceCompanyList, confirmCompanyResponseList);
        maintenanceCompanyPage.setRecords(confirmCompanyResponseList);
        return RestResponse.success(maintenanceCompanyPage, ApiConstants.RESULT_SUCCESS, "获取认证企业数据成功");
    }

    @Override
    public Map<String, List<MaintenanceCompany>> getProvinceCodeToMaintenanceCompany() {
        Map<String, List<MaintenanceCompany>> provinceCodeToMaintenanceCompany = new HashMap<>();
        //获取认证企业
        List<MaintenanceCompany> maintenanceCompanyList = list(new QueryWrapper<MaintenanceCompany>()
                .eq("is_certificated", ApiConstants.CompanyConstants.MAINTENANCE_PASS)
        );
        //将公司数据通过省份编码分组
        if (maintenanceCompanyList != null && maintenanceCompanyList.size() > 0) {
            provinceCodeToMaintenanceCompany = maintenanceCompanyList.stream()
                    .collect(Collectors.groupingBy(maintenanceCompany -> {
                        if (StringUtils.isNotBlank(maintenanceCompany.getProvinceCode())) {
                            return maintenanceCompany.getProvinceCode();
                        }
                        return "0001";
                    }));
        }
        return provinceCodeToMaintenanceCompany;
    }

    @Override
    public RestResponse teamInfo(MaintenanceCompanyRequest maintenanceCompanyRequest) {
        MaintenanceCompany maintenanceCompany = this.getById(maintenanceCompanyRequest.getCompanyId());
        //设置团队人数
        setCompanyUserNum(Collections.singletonList(maintenanceCompany));
        TeamInfoResponse teamInfoResponse = new TeamInfoResponse();
        teamInfoResponse.setName(maintenanceCompany.getName());
        teamInfoResponse.setCorporator(maintenanceCompany.getCorporator());
        teamInfoResponse.setTelephone(maintenanceCompany.getTelephone());
        teamInfoResponse.setCreateDate(maintenanceCompany.getCreateDate());
        teamInfoResponse.setRemarks(maintenanceCompany.getRemarks());
        teamInfoResponse.setIsCertificated(maintenanceCompany.getIsCertificated());
        teamInfoResponse.setLogoImg(maintenanceCompany.getLogoImg());
        teamInfoResponse.setUserNum(maintenanceCompany.getUserNum());
        if (maintenanceCompanyRequest.getUserId().equals(maintenanceCompany.getCreatorId())) {
            teamInfoResponse.setManagerFlag(true);
        }
        return RestResponse.success(teamInfoResponse, ApiConstants.RESULT_SUCCESS, "获取团队详情成功");
    }

    /**
     * @param
     * @return
     * @description 封装认证企业信息
     * @date 2020/2/19 11:18 上午
     */
    private void packConfirmCompany(List<MaintenanceCompany> maintenanceCompanyList,
                                    List<ConfirmCompanyResponse> confirmCompanyResponseList) {
        if (maintenanceCompanyList != null && maintenanceCompanyList.size() > 0) {
            //获取公司id集合
            List<Long> companyIdList = maintenanceCompanyList.stream()
                    .map(MaintenanceCompany::getId).collect(Collectors.toList());
            //设置企业团队人数
            setCompanyUserNum(maintenanceCompanyList);

            //将信息封装为 mtCompanyId(公司id) -> dealTime(处理时间)
            Map<Long, LocalDateTime> companyIdToDealTime = mtCompanyAttestationService.
                    getMtCompanyIdToDealTime(companyIdList);

            //获取公司项目数
            Map<Long, Long> mtCompanyIdToProjectNum = mtCompanyIdToNum(commonDataMapper.
                    getMtCompanyIdToProjectNum(new MaintenanceCompanyRequest(companyIdList)));

            //获取公司电梯信息
            Map<Long, List<LiftMapDataModel>> companyIdToLiftData = getMtCompanyIdToLiftData(companyIdList);

            //获取公司维保记录数
            Map<Long, Long> mtCompanyIdToMtRecordNum = mtCompanyIdToNum(commonDataMapper.getMtCompanyIdToMtRecord(
                    new MaintenanceCompanyRequest(companyIdList)));

            //获取公司急修记录数
            Map<Long, Long> mtCompanyIdToEmergencyRecordNum = mtCompanyIdToNum(
                    commonDataMapper.getMtCompanyIdToEmergencyRecord(new MaintenanceCompanyRequest(companyIdList)));

            //循环设置认证公司信息
            for (MaintenanceCompany maintenanceCompany : maintenanceCompanyList) {
                //设置认证企业信息
                setConfirmCompany(confirmCompanyResponseList, companyIdToDealTime, mtCompanyIdToProjectNum,
                        companyIdToLiftData, mtCompanyIdToMtRecordNum, mtCompanyIdToEmergencyRecordNum, maintenanceCompany);
            }
        }
    }

    /**
     * @param
     * @return
     * @description 设置认证企业信息
     * @date 2020/2/19 6:53 下午
     */
    private void setConfirmCompany(List<ConfirmCompanyResponse> confirmCompanyResponseList,
                                   Map<Long, LocalDateTime> companyIdToDealTime,
                                   Map<Long, Long> mtCompanyIdToProjectNum,
                                   Map<Long, List<LiftMapDataModel>> companyIdToLiftData,
                                   Map<Long, Long> mtCompanyIdToMtRecordNum,
                                   Map<Long, Long> mtCompanyIdToEmergencyRecordNum, MaintenanceCompany maintenanceCompany) {
        ConfirmCompanyResponse confirmCompanyResponse = new ConfirmCompanyResponse(maintenanceCompany);
        //设置认证时间
        if (companyIdToDealTime.size() > 0) {
            confirmCompanyResponse.setConfirmTime(companyIdToDealTime.get(maintenanceCompany.getId()));
        }
        //设置公司项目数
        if (mtCompanyIdToProjectNum != null && mtCompanyIdToProjectNum.size() > 0) {
            confirmCompanyResponse.setProjectNum(getLong(mtCompanyIdToProjectNum.get(maintenanceCompany.getId())));
        }
        setLiftUnitsNum(companyIdToLiftData, maintenanceCompany, confirmCompanyResponse);
        //设置公司维保数
        if (mtCompanyIdToMtRecordNum != null && mtCompanyIdToMtRecordNum.size() > 0) {
            confirmCompanyResponse.setMaintenanceNum(getLong(mtCompanyIdToMtRecordNum.get(maintenanceCompany.getId())));
        }
        //设置公司急修数
        if (mtCompanyIdToEmergencyRecordNum != null && mtCompanyIdToEmergencyRecordNum.size() > 0) {
            confirmCompanyResponse.setEmergencyNum(getLong(mtCompanyIdToEmergencyRecordNum.get(maintenanceCompany.getId())));
        }
        //设置最后活跃时间
        confirmCompanyResponseList.add(confirmCompanyResponse);
    }

    /**
     * @param
     * @return
     * @description 获取公司id -> 电梯数据
     * @date 2020/2/19 2:21 下午
     */
    private Map<Long, List<LiftMapDataModel>> getMtCompanyIdToLiftData(List<Long> companyIdList) {
        List<LiftMapDataModel> liftMapDataModelList = homeLiftDataMapper.getCompanyLiftData(new LiftDataRequest(companyIdList));
        Map<Long, List<LiftMapDataModel>> companyIdToLiftData = new HashMap<>();
        if (liftMapDataModelList != null && liftMapDataModelList.size() > 0) {
            companyIdToLiftData = liftMapDataModelList.stream()
                    .collect(Collectors.groupingBy(LiftDataResponse::getMtCompanyId));
        }
        return companyIdToLiftData;
    }

    /**
     * @param
     * @return
     * @description 设置电梯台量数据
     * @date 2020/2/19 2:22 下午
     */
    private void setLiftUnitsNum(Map<Long, List<LiftMapDataModel>> companyIdToLiftData,
                                 MaintenanceCompany maintenanceCompany,
                                 ConfirmCompanyResponse confirmCompanyResponse) {
        //设置电梯台量
        if (companyIdToLiftData.size() > 0) {
            List<LiftMapDataModel> liftMapDataModels = companyIdToLiftData.get(maintenanceCompany.getId());
            if (liftMapDataModels != null && liftMapDataModels.size() > 0) {
                //总台量
                long totalLiftNum = liftMapDataModels.stream().count();
                //总停保台量
                long totalStopLiftNum = liftMapDataModels.stream()
                        .filter(liftMapDataModel -> {
                            return StringUtils.isNotBlank(liftMapDataModel.getLiftCompanyStatus()) &&
                                    CommonEnum.LiftStatus.STOP_INSURANCE.equals(liftMapDataModel.getLiftCompanyStatus());
                        }).count();
                //总活跃台量
                long totalActiveLiftNum = totalLiftNum - totalStopLiftNum;
                confirmCompanyResponse.setTotalLiftNum(totalLiftNum);
                confirmCompanyResponse.setActiveLiftNum(totalActiveLiftNum);
                confirmCompanyResponse.setStopLiftNum(totalStopLiftNum);
            }
        }
    }

    /**
     * @param
     * @return
     * @description 将条数集合转化为 公司id -> 条数
     * @date 2020/2/24 2:06 下午
     */
    private Map<Long, Long> mtCompanyIdToNum(List<CountDataModel> countDataModelList) {
        Map<Long, Long> mtCompanyIdToNum = new HashMap<>();
        //将list转化为map
        if (countDataModelList != null && countDataModelList.size() > 0) {
            countDataModelList.forEach(countDataModel -> {
                long count = countDataModel.getDataCount() != null ? countDataModel.getDataCount() : 0L;
                mtCompanyIdToNum.put(countDataModel.getMtCompanyId(), count);
            });
        }
        return mtCompanyIdToNum;
    }

    private long getLong(Long longValue) {
        if (longValue != null) {
            return longValue;
        }
        return 0L;
    }

}
