package com.hys.app.service.erp.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hys.app.controller.erp.use.msg.MsgContant;
import com.hys.app.controller.erp.use.msg.MsgUtilClient;
import com.hys.app.converter.erp.CompanyConverter;
import com.hys.app.framework.context.user.AdminUserContext;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.util.JsonUtil;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.mapper.erp.CompanyErpMapper;
import com.hys.app.mapper.system.AdminUserMapper;
import com.hys.app.mapper.system.RoleMapper;
import com.hys.app.model.erp.entity.*;
import com.hys.app.model.system.dos.AdminUser;
import com.hys.app.model.system.dos.RoleDO;
import com.hys.app.model.system.vo.Menus;
import com.hys.app.service.erp.CompanyBandMsgManager;
import com.hys.app.service.erp.CompanyErpManager;
import com.hys.app.service.erp.CompanyPackageManager;
import com.hys.app.util.PinYingUtil;
import com.hys.app.util.ValidateUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 平台管理员业务类
 *
 * @author zh
 * @version v7.0
 * @since v7.0.0
 * 2018-06-20 20:38:26
 */
@Service
@AllArgsConstructor
public class CompanyErpManagerImpl extends ServiceImpl<CompanyErpMapper, CompanyErp> implements CompanyErpManager {
    private RedisTemplate redisTemplate;
    private CompanyPackageManager companyPackageManager;
    private AdminUserMapper adminUserMapper;
    private MsgUtilClient msgUtilClient;
    private CompanyBandMsgManager companyBandMsgManager;
    private RoleMapper roleMapper;




    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createCompany(CompanyDO companyDO) {
        String code = (String)redisTemplate.opsForValue().get(companyDO.getCheckCodeKey());
        if (StrUtil.isNotBlank(companyDO.getCheckCode()) && !code.equals(companyDO.getCheckCode())){
            throw new ServiceException("验证码错误");
        }
        CompanyPackage byId = companyPackageManager.getById(companyDO.getCompanyPackageId());
        if (ObjectUtil.isNull(byId)) {
            throw new ServiceException("套餐不存在");
        }
        CompanyErp convert = CompanyConverter.INSTANCE.convert(companyDO);

        convert.setThisDay(byId.getDay());
        convert.setThisMoney(byId.getMoney());
        convert.setThisRoleId(byId.getId());
        convert.setThisUserNum(byId.getUserNum());
        convert.setThisCompanyPackageId(byId.getId());

        convert.setRoleId(byId.getRoleId());
        convert.setUserNum(byId.getUserNum());
        convert.setMoney(new BigDecimal(0));

        checkParam(convert);

        Date currentDate = new Date();
        // 使用 Calendar 加上15天
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, byId.getDay());
        convert.setEndUseTime(calendar.getTime());
        convert.setPinying(PinYingUtil.toPinyin(companyDO.getName()));
        String pinyinFirstLetter = PinYingUtil.toPinyinFirstLetter(companyDO.getName());
        convert.setFirstPy(pinyinFirstLetter);
        convert.setFirstPyLower(pinyinFirstLetter.toLowerCase());


        save(convert);
        //给公司创建初始账号
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            int index = random.nextInt(characters.length());
            sb.append(characters.charAt(index));
        }
        String password = sb.toString();
        //管理员信息入库
        AdminUser adminUser = new AdminUser();
        adminUser.setCompanyId(convert.getId());
        adminUser.setUsername("admin");
        adminUser.setRoleId(convert.getRoleId());
        adminUser.setFounder(0);
        adminUser.setNickname(convert.getName() + "管理员");
        adminUser.setPassword(StringUtil.md5("admin"+password+convert.getId()));

        adminUser.setDateLine(com.hys.app.framework.util.DateUtil.getDateline());
        adminUser.setUserState(0);
        adminUser.setFirstPassword(password);
        adminUser.setPhone(convert.getPhone());
        adminUser.setEmail(convert.getEmail());
        //把这个管理员能看到的所有页面保存起来
        RoleDO roleDO = roleMapper.selectById(byId.getRoleId());
        List<Menus> menus = JsonUtil.jsonToList(roleDO.getAuthIds(), Menus.class);
        List<Menus> list = new ArrayList<>();
        for (Menus menu : menus) {
            if (CollUtil.isNotEmpty(menu.getChildren())) {
                list.add(menu);
                getMenus(list, menu);
            } else {
                list.add(menu);
            }
        }
        //这个角色所有已勾选的菜单
        Set<Menus> collect = list.stream().filter(Menus::isChecked).collect(Collectors.toSet());
        for (Menus menus1 : collect) {
            menus1.setChildren(collect.stream().filter(item -> item.getParentId().equals(menus1.getId())).collect(Collectors.toList()));
        }
        List<Menus> collect2 = collect.stream().filter(item -> item.getParentId() == 0).collect(Collectors.toList());


        adminUser.setAuthIds(JSON.toJSONString(collect2));
        adminUserMapper.insert(adminUser);


        //  发消息
        msgUtilClient.sendSys(MsgContant.CREATE_COMPANY_SYSTEM, adminUser, "admin",password, LocalDateTime.now().plusDays(15).format(DateTimeFormatter.ISO_LOCAL_DATE),"13127911751");
        msgUtilClient.sendMail(MsgContant.CREATE_COMPANY_MAIL, adminUser, "admin",password, LocalDateTime.now().plusDays(15).format(DateTimeFormatter.ISO_LOCAL_DATE),"13127911751");
        //todo 模板没审核通过
        msgUtilClient.sendSms(MsgContant.CREATE_COMPANY_SMS, adminUser, "admin",password, LocalDateTime.now().plusDays(15).format(DateTimeFormatter.ISO_LOCAL_DATE),"13127911751");

//        List<String> companyBandMsg = companyBandMsgManager.getCompanyBandMsgCode(convert.getId());

        return password;
    }

    private void getMenus(List<Menus> list, Menus menus) {
        for (Menus child : menus.getChildren()) {
            list.add(child);
            getMenus(list, child);
        }
    }

    @Override
    public Long updateCompany(CompanyDO companyUpdateDO, Long id) {
        CompanyErp company = ValidateUtil.getOne(baseMapper, CompanyErp::getId, id, "企业");
        CompanyConverter.INSTANCE.convert(company, companyUpdateDO);
        updateById(company);
        return id;
    }

    @Override
    public Long renewCompany(Long id, Long packageId) {
        CompanyErp byId = getById(id);
        if (ObjectUtil.isNull(byId)) {
            throw new ServiceException("未查询到公司信息");
        }
        CompanyPackage companyPackage = companyPackageManager.getById(packageId);
        if (ObjectUtil.isNull(companyPackage)) {
            throw new ServiceException("未查询到套餐包");
        }
        byId.setThisCompanyPackageId(packageId);
        byId.setThisMoney(companyPackage.getMoney().add(renewCompanyDifference(packageId)));
        byId.setThisDay(companyPackage.getDay());
        byId.setThisUserNum(companyPackage.getUserNum());
        byId.setThisRoleId(companyPackage.getRoleId());
        updateById(byId);
        return null;
    }

    @Override
    public CompanyVO getOneCompany(Long id) {
        return CompanyConverter.INSTANCE.convert(ValidateUtil.getOne(baseMapper, CompanyErp::getId, id, "企业"));
    }

    @Override
    public IPage<CompanyVO> getPage(CompanyQuery query) {

        Page<CompanyErp> page = this.baseMapper.selectPage(new Page<>(query.getPageNo(), query.getPageSize()),
                new LambdaQueryWrapper<CompanyErp>().like(StrUtil.isNotBlank(query.getName()), CompanyErp::getName, query.getName())
                        .like(StrUtil.isNotBlank(query.getIndustry()), CompanyErp::getIndustry, query.getIndustry())
                        .like(StrUtil.isNotBlank(query.getUserName()), CompanyErp::getUserName, query.getUserName())
                        .ge(ObjectUtil.isNotNull(query.getHasUse()), CompanyErp::getEndUseTime, LocalDateTime.now())
                        .eq(!AdminUserContext.hasFound(), CompanyErp::getId, AdminUserContext.getCompanyId()));
        Page<CompanyVO> convert = CompanyConverter.INSTANCE.convert(page);
        for (CompanyVO vo : convert.getRecords()) {
            //todo 人员做好了之后统计人数
            vo.setCurrentUserNum(1);
        }
        return convert;
    }

    @Override
    public BigDecimal renewCompanyDifference(Long id) {
        CompanyErp company = getById(AdminUserContext.getCompanyId());
        if (id.equals(company.getCompanyPackageId())) {
            return BigDecimal.valueOf(0);
        }
        CompanyPackage changePackage = companyPackageManager.getById(id);
        CompanyPackage usePackage = companyPackageManager.getById(company.getCompanyPackageId());
        BigDecimal subtract = changePackage.getMoney().divide(BigDecimal.valueOf(changePackage.getDay()))
                .subtract(usePackage.getMoney().divide(BigDecimal.valueOf(usePackage.getDay())));
        if (subtract.compareTo(BigDecimal.ZERO) < 0) {
            return BigDecimal.ZERO;
        }
        long betweenDay = DateUtil.betweenDay(new Date(), company.getEndUseTime(), true);
        return subtract.multiply(BigDecimal.valueOf(betweenDay));
    }

    @Override
    public Long superUpdateStatus(Long id, CompanyStatusDO companyStatusDO) {
        CompanyErp byId = getById(id);
        if (ObjectUtil.isNull(byId)){
            throw new ServiceException("未查询到公司信息");
        }
        byId.setStatus(companyStatusDO.getStatus());
        byId.setFailReason(companyStatusDO.getFailReason());
        updateById(byId);
        return id;
    }


    private void checkParam(CompanyErp convert) {
        if (Pattern.matches(".*[\\u4e00-\\u9fa5\\p{P}].*", convert.getCreditCode())) {
            throw new ServiceException("统一社会信用代码不能包含中文和特殊符号");
        }
        if (ValidateUtil.checkRepeat(baseMapper, CompanyErp::getCreditCode, convert.getCreditCode(), CompanyErp::getId, convert.getId())) {
            throw new ServiceException("统一社会代码已存在");
        }
        if (ValidateUtil.checkRepeat(baseMapper, CompanyErp::getName, convert.getName(), CompanyErp::getId, convert.getId())) {
            throw new ServiceException("公司名称重复");
        }
    }

}
