package com.fs.company.service.impl;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fs.common.constant.FsConstants;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.SecurityUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.*;
import com.fs.company.mapper.*;
import com.fs.company.param.CompanyLiveShowParam;
import com.fs.company.param.CompanyParam;
import com.fs.company.service.ICompanyMiniappService;
import com.fs.company.service.ICompanyProfitService;
import com.fs.company.service.ICompanyRoleService;
import com.fs.company.vo.*;
import com.fs.course.mapper.FsCourseRedPacketLogMapper;
import com.fs.his.config.StoreConfig;
import com.fs.his.domain.FsInquiryOrder;
import com.fs.his.domain.FsStoreOrder;
import com.fs.his.domain.FsStorePayment;
import com.fs.his.dto.InquiryConfigDTO;
import com.fs.his.mapper.FsStoreOrderMapper;
import com.fs.his.vo.OptionsVO;
import com.fs.hisStore.domain.FsStoreOrderScrm;
import com.fs.hisStore.domain.FsStorePaymentScrm;
import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
import com.fs.live.domain.LiveOrder;
import com.fs.live.mapper.LiveOrderMapper;
import com.fs.live.service.ILiveService;
import com.fs.store.config.CompanyMenuConfig;
import com.fs.system.domain.SysConfig;
import com.fs.system.mapper.SysConfigMapper;
import com.fs.system.service.ISysConfigService;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.fs.company.service.ICompanyService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import static com.fs.company.service.impl.CompanyMiniappServiceImpl.GET_MINI_APP_STR;

/**
 * 企业Service业务层处理
 *
 * @author fs
 * @date 2021-10-04
 */
@Service
public class CompanyServiceImpl implements ICompanyService
{
    Logger logger= LoggerFactory.getLogger(getClass());;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private ICompanyMiniappService companyMiniappService;
    @Autowired
    private CompanyDeptMapper deptMapper;
    @Autowired
    private ICompanyRoleService roleService;
    @Autowired
    private CompanyRoleMapper roleMapper;
    @Autowired
    private CompanyPostMapper postMapper;
    @Autowired
    private CompanyUserMapper userMapper;
    @Autowired
    private CompanyUserRoleMapper userRoleMapper;
    @Autowired
    private CompanyUserPostMapper userPostMapper;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private CompanyMoneyLogsMapper moneyLogsMapper;
    @Autowired
    private FsStoreOrderMapper storeOrderMapper;

    @Autowired
    private FsStoreOrderScrmMapper storeOrderScrmMapper;
    @Autowired
    private ICompanyProfitService companyProfitService;
    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private CompanyDeptMapper companyDeptMapper;

    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private FsCourseRedPacketLogMapper fsCourseRedPacketLogMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private ILiveService liveService;
    @Autowired
    private LiveOrderMapper liveOrderMapper;


    @Override
    public List<CompanyVO> liveShowList(CompanyParam param) {
        return companyMapper.liveShowList(param);
    }

    @Override
    public void batchUpdateLiveShow(CompanyLiveShowParam param) {
        companyMapper.batchUpdateLiveShow(param);
        liveService.asyncToCache();
    }

    @Override
    @Transactional
    public void addCompanyTuiLiveMoney(LiveOrder order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                String json =configService.selectConfigByKey("store.config");
                com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
                //支付金额-（订单金额*rate%）
                Double rate=config.getTuiMoneyRate()/100d;
                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
                logger.info("写入公司推广佣金:"+tuiMoney);
                company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                companyMapper.updateCompany(company);
                LiveOrder storeOrderMap=new LiveOrder();
                storeOrderMap.setOrderId(order.getOrderId());
                storeOrderMap.setTuiMoney(tuiMoney);
                liveOrderMapper.updateLiveOrder(storeOrderMap);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
    public void subLiveCompanyMoney(LiveOrder order) {
        if(order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
                companyMapper.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金退款");
                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
                log.setLogsType(5);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getOrderId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    @Override
    public List<OptionsVO> selectAllCompanyList(Long deptId) {
        return companyMapper.selectAllCompanyList(deptId);
    }

    /**
     * 查询企业
     *
     * @param companyId 企业ID
     * @return 企业
     */
    @Override
    public Company selectCompanyById(Long companyId){
        Company company = companyMapper.selectCompanyById(companyId);
        if(company != null) {
            List<CompanyMiniapp> miniApp = companyMiniappService.getMiniAppListByCompanyList(Collections.singletonList(company.getCompanyId()));
            company.setMiniAppMaster(GET_MINI_APP_STR.apply(0, miniApp));
            company.setMiniAppServer(GET_MINI_APP_STR.apply(1, miniApp));
        }
        return company;
    }

    /**
     * 查询企业列表
     *
     * @param company 企业
     * @return 企业
     */
    @Override
    public List<Company> selectCompanyList(Company company)
    {
        return companyMapper.selectCompanyList(company);
    }

    /**
     * 新增企业
     *
     * @param company 企业
     * @return 结果
     */
    @Override
    @Transactional
    public R insertCompany(Company company)
    {
        //帐号是否存在
        if(userMapper.checkUserName(company.getUserName())>0){
            return R.error("管理员帐号已存在");
        }
        company.setCreateTime(DateUtils.getNowDate());
        if(companyMapper.insertCompany(company)>0){
            //写入帐号信息
            //创建部门
            CompanyDept dept=new CompanyDept();
            dept.setCompanyId(company.getCompanyId());
            dept.setParentId(0l);
            dept.setAncestors("0");
            dept.setStatus("0");
            dept.setCreateTime(new Date());
            dept.setDeptName(company.getCompanyName());
            deptMapper.insertCompanyDept(dept);

            //创建销售部门
            CompanyDept saleDept=new CompanyDept();
            saleDept.setParentId(0l);
            saleDept.setAncestors("0");
            saleDept.setStatus("0");
            saleDept.setDeptName("销售(默认部门)");
            saleDept.setCreateTime(new Date());
            saleDept.setParentId(dept.getDeptId());
            saleDept.setCompanyId(company.getCompanyId());
            deptMapper.insertCompanyDept(saleDept);

            //创建岗位
            CompanyPost post=new CompanyPost();
            post.setCompanyId(company.getCompanyId());
            post.setPostCode("manager");
            post.setPostName("管理员");
            post.setPostSort(0);
            post.setStatus("0");
            postMapper.insertCompanyPost(post);

            //创建销售岗位
            CompanyPost salePost=new CompanyPost();
            salePost.setCompanyId(company.getCompanyId());
            salePost.setPostCode("default_sale");
            salePost.setPostName("销售");
            salePost.setPostSort(0);
            salePost.setStatus("0");
            postMapper.insertCompanyPost(salePost);

            //创建角色
            // 创建管理员角色（拥有全部权限）
            CompanyRole adminRole = new CompanyRole();
            adminRole.setCompanyId(company.getCompanyId());
            adminRole.setRoleName("管理员");
            adminRole.setRoleKey("admin");
            adminRole.setRoleSort(0);
            adminRole.setStatus("0");
            roleMapper.insertCompanyRole(adminRole);

            // 创建销售角色（新增部分，只有"我的"相关权限）
            CompanyRole salesRole = new CompanyRole();
            salesRole.setCompanyId(company.getCompanyId());
            salesRole.setRoleName(company.getCompanyName() + "_销售");
            salesRole.setRoleKey(company.getCompanyId()+"_sales");
            salesRole.setRoleSort(1);
            salesRole.setDataScope("5");
            salesRole.setStatus("0");
            //增加销售角色菜单权限
            try {
                String json = configService.selectConfigByKey("companymenu.config");
                if (StringUtils.isNotEmpty(json) && !json.equals("")) {
                    CompanyMenuConfig config = JSONUtil.toBean(json, CompanyMenuConfig.class);
                    salesRole.setMenuIds(config.getMenuIds());
                    if(config.getMenuIds().length > 0){
                        roleService.insertRole(salesRole);
                    }else {
                        roleService.insertDefaultRole(salesRole);
                    }
                }else {
                    roleService.insertDefaultRole(salesRole);
                }

            } catch (Exception e) {
                logger.error("获取菜单配置失败", e);
            }

            //添加用户
            CompanyUser user=new CompanyUser();
            user.setCompanyId(company.getCompanyId());
            user.setNickName("管理员");
            user.setPassword(SecurityUtils.encryptPassword(company.getPassword()));
            user.setUserName(company.getUserName());
            user.setDeptId(dept.getDeptId());
            user.setUserType("00");
            user.setPhonenumber(company.getCompanyMobile());
            user.setSex("0");
            user.setStatus("0");
            user.setIsDel(0);
            user.setIsAudit(1);
            userMapper.insertCompanyUser(user);
            //添加用户角色表
            CompanyUserRole userRole=new CompanyUserRole();
            userRole.setRoleId(adminRole.getRoleId());
            userRole.setUserId(user.getUserId());
            userRoleMapper.insertCompanyUserRole(userRole);
            //添加用户岗位表
            CompanyUserPost userPost=new CompanyUserPost();
            userPost.setPostId(post.getPostId());
            userPost.setUserId(user.getUserId());
            userPostMapper.insertCompanyUserPost(userPost);
            company.setUserId(user.getUserId());
            companyMapper.updateCompany(company);
            bindMiniApp(company);
            return R.ok();
        }
        else
        {
            return R.error("操作失败");
        }
    }

    /**
     * 修改企业
     *
     * @param company 企业
     * @return 结果
     */
    @Override
    public int updateCompany(Company company)
    {
        company.setUpdateTime(DateUtils.getNowDate());
        if(company.isUpdateMiniApp()){
            bindMiniApp(company);
        }
        return companyMapper.updateCompany(company);
    }
    // 绑定小程序
    public void bindMiniApp(Company company){
        companyMiniappService.removeByCompanyId(company.getCompanyId());
        List<String> miniAppMaster = company.getMiniAppMaster();
        if(miniAppMaster != null && !miniAppMaster.isEmpty()){
            companyMiniappService.insertBatch(miniAppMaster, company.getCompanyId(), 0);
        }
        List<String> miniAppServer = company.getMiniAppServer();
        if(miniAppServer != null && !miniAppServer.isEmpty()){
            companyMiniappService.insertBatch(miniAppServer, company.getCompanyId(), 1);
        }

    }

    /**
     * 批量删除企业
     *
     * @param companyIds 需要删除的企业ID
     * @return 结果
     */
    @Override
    public int deleteCompanyByIds(Long[] companyIds)
    {
        int i = companyMapper.deleteCompanyByIds(companyIds);
        //删除对应部门
        if (i > 0){
            companyDeptMapper.deleteCompanyDeptByCompanyIds(companyIds);
        }
        return i;
    }

    /**
     * 删除企业信息
     *
     * @param companyId 企业ID
     * @return 结果
     */
    @Override
    public int deleteCompanyById(Long companyId)
    {
        return companyMapper.deleteCompanyById(companyId);
    }

    @Override
    public List<CompanyVO> selectCompanyVOList(CompanyParam param) {
        return companyMapper.selectCompanyVOList(param);
    }

    @Override
    public List<CompanyNameVO> selectCompanyNameVOList(CompanyParam param) {
        return companyMapper.selectCompanyNameVOList(param);
    }


    @Override
    public List<CompanyCrmVO> selectCompanyCrmDayCountList(CompanyParam param) {
        return companyMapper.selectCompanyCrmDayCountList(param);
    }

    @Override
    public Integer selectCompanyCount() {
        return companyMapper.selectCompanyCount();
    }

    @Override
    @Transactional
    public void addCompanyTuiMoney(FsStoreOrder order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                String json =configService.selectConfigByKey("his.store");
                StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
                //支付金额-（订单金额*rate%）
                Double rate=config.getTuiMoneyRate()/100d;
                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
                logger.info("写入公司推广佣金:"+tuiMoney);
                company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                companyMapper.updateCompany(company);
                FsStoreOrder storeOrderMap=new FsStoreOrder();
                storeOrderMap.setOrderId(order.getOrderId());
                storeOrderMap.setTuiMoney(tuiMoney);
                storeOrderMapper.updateFsStoreOrder(storeOrderMap);
            }
        }
    }

    @Override
    @Transactional
    public void addCompanyTuiMoney(FsStoreOrderScrm order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                String json =configService.selectConfigByKey("his.store");
                StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
                //支付金额-（订单金额*rate%）
                if (config.getTuiMoneyRate()!=null){
                    Double rate=config.getTuiMoneyRate()/100d;
                    BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
                    logger.info("写入公司推广佣金:"+tuiMoney);
                    company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                    companyMapper.updateCompany(company);
                    FsStoreOrderScrm storeOrderMap=new FsStoreOrderScrm();
                    storeOrderMap.setId(order.getId());
                    storeOrderMap.setTuiMoney(tuiMoney);
                    storeOrderScrmMapper.updateFsStoreOrder(storeOrderMap);
                }
            }
        }
    }

    @Override
    @Transactional
    public void addCompanyMoney(FsStoreOrder order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                FsStoreOrder orderMap=new FsStoreOrder();
                orderMap.setOrderId(order.getOrderId());
                orderMap.setTuiMoneyStatus(1);
                storeOrderMapper.updateFsStoreOrder(orderMap);
                BigDecimal money = order.getPayMoney().add(order.getPayRemain());
                company.setMoney(company.getMoney().add(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("佣金入账");
                log.setMoney(money);
                log.setLogsType(3);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getOrderId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
                FsStoreOrder fsStoreOrder = new FsStoreOrder();
                fsStoreOrder.setOrderId(order.getOrderId());
                fsStoreOrder.setTuiMoneyStatus(1);
                storeOrderMapper.updateFsStoreOrder(fsStoreOrder);
            }
        }
    }

    @Override
    @Transactional
    public void addCompanyMoney(FsStoreOrderScrm order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                FsStoreOrder orderMap=new FsStoreOrder();
                orderMap.setOrderId(order.getId());
                orderMap.setTuiMoneyStatus(1);
                storeOrderMapper.updateFsStoreOrder(orderMap);
                // order.getPayRemain() 数据库实际没有这个字段了 直接使用 应付金额
                BigDecimal money = order.getPayPrice();
                company.setMoney(company.getMoney().add(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("佣金入账");
                log.setMoney(money);
                log.setLogsType(3);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
                FsStoreOrderScrm fsStoreOrder = new FsStoreOrderScrm();
                fsStoreOrder.setId(order.getId());
                fsStoreOrder.setTuiMoneyStatus(1);
                storeOrderScrmMapper.updateFsStoreOrder(fsStoreOrder);
            }
        }
    }

    @Override
    public void addCompanyMoney(LiveOrder order) {
        if(order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
                companyMapper.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金退款");
                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
                log.setLogsType(4);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getOrderId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);

            }
        }
    }

    @Override
    @Transactional
    public void subCompanyMoney(FsStoreOrder order) {
        if(order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
                companyMapper.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金退款");
                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
                log.setLogsType(4);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getOrderId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);



            }
        }
    }

    @Override
    @Transactional
    public void subCompanyMoney(FsStoreOrderScrm order) {
        if(order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
                companyMapper.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金退款");
                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
                log.setLogsType(4);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);



            }
        }
    }

    @Override
    public Company selectCompanyByAppId(String appId) {
        return companyMapper.selectCompanyByAppId(appId);
    }

    @Override
    @Async
    public void resetMoney(Long companyId) {
//        Company company=companyMapper.selectCompanyById(companyId);
//        company.setMoney(new BigDecimal(0));
//        company.setTuiMoney(new BigDecimal(0));
//        //删除公司的提现记录
//        companyProfitService.deleteCompanyProfitByCompanyId(companyId);
//        //删除公司的金额记录
//        moneyLogsMapper.deleteCompanyMoneyLogsByCompanyId(companyId);
//        //重新计算金额
//        Integer pageNum=1;
//        while (true){
//            PageHelper.startPage(pageNum, 10);
//            List<FsStoreOrder> list=storeOrderMapper.selectFsStoreOrderByCompanyId(companyId);
//            pageNum++;
//            if(list!=null&&list.size()>0){
//                for(FsStoreOrder order:list){
//                    //已签收
//                    if(order.getStatus()==3&&order.getTuiMoney()!=null&&order.getTuiMoney().compareTo(new BigDecimal(0))==1){
////                        String json =configService.selectConfigByKey("his.store");
////                        StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
////                        Double rate=config.getTuiMoneyRate()/100d;
////                        BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
//                        company.setMoney(company.getMoney().add(order.getTuiMoney()));
//                        company.setTuiMoney(company.getTuiMoney().add(order.getTuiMoney()));
//                        companyMapper.updateCompany(company);
//                        //写入日志
//                        CompanyMoneyLogs log=new CompanyMoneyLogs();
//                        log.setCompanyId(order.getCompanyId());
//                        log.setRemark("订单佣金入帐");
//                        log.setMoney(order.getTuiMoney());
//                        log.setLogsType(4);
//                        log.setBalance(company.getMoney());
//                        log.setCreateTime(new Date());
//                        log.setBusinessId(order.getId().toString());
//                        moneyLogsMapper.insertCompanyMoneyLogs(log);
//                    }
//                }
//            }
//            else{
//                break;
//            }
//        }
        //计算所有的收款记录，写入

//        company.setMoney(company.getMoney().add(order.getTuiMoney()));
//        company.setTuiMoney(company.getTuiMoney().add(order.getTuiMoney()));
//        companyMapper.updateCompany(company);
    }

    @Override
    @Transactional
    public void addCompanyPaymentMoney(FsStorePayment storePayment) {
        Company company=companyMapper.selectCompanyByIdForUpdate(storePayment.getCompanyId());
        if(company!=null){
            company.setMoney(company.getMoney().add(storePayment.getPayMoney()));
            company.setTuiMoney(company.getTuiMoney().add(storePayment.getPayMoney()));
            companyMapper.updateCompany(company);
            //写入日志
            CompanyMoneyLogs log=new CompanyMoneyLogs();
            log.setCompanyId(storePayment.getCompanyId());
            log.setRemark("收款佣金入帐");
            log.setMoney(storePayment.getPayMoney());
            log.setLogsType(8);
            log.setBalance(company.getMoney());
            log.setCreateTime(new Date());
            log.setBusinessId(storePayment.getPaymentId().toString());
            moneyLogsMapper.insertCompanyMoneyLogs(log);


        }

    }

    @Override
    @Transactional
    public void addCompanyPaymentMoney(FsStorePaymentScrm storePayment) {
        Company company=companyMapper.selectCompanyByIdForUpdate(storePayment.getCompanyId());
        if(company!=null){
            company.setMoney(company.getMoney().add(storePayment.getPayMoney()));
            company.setTuiMoney(company.getTuiMoney().add(storePayment.getPayMoney()));
            companyMapper.updateCompany(company);
            //写入日志
            CompanyMoneyLogs log=new CompanyMoneyLogs();
            log.setCompanyId(storePayment.getCompanyId());
            log.setRemark("收款佣金入帐");
            log.setMoney(storePayment.getPayMoney());
            log.setLogsType(8);
            log.setBalance(company.getMoney());
            log.setCreateTime(new Date());
            log.setBusinessId(storePayment.getPaymentId().toString());
            moneyLogsMapper.insertCompanyMoneyLogs(log);


        }

    }

    @Override
    @Transactional
    public void subCompanyPaymentMoney(FsStorePayment payment) {
        Company company=companyMapper.selectCompanyByIdForUpdate(payment.getCompanyId());
        if(company!=null){
            company.setMoney(company.getMoney().subtract(payment.getRefundMoney()));
            company.setTuiMoney(company.getTuiMoney().subtract(payment.getRefundMoney()));
            companyMapper.updateCompany(company);
            //写入日志
            CompanyMoneyLogs log=new CompanyMoneyLogs();
            log.setCompanyId(payment.getCompanyId());
            log.setRemark("收款佣金退款");
            log.setMoney(payment.getRefundMoney().multiply(new BigDecimal(-1)));
            log.setLogsType(9);
            log.setBalance(company.getMoney());
            log.setCreateTime(new Date());
            log.setBusinessId(payment.getPaymentId().toString());
            moneyLogsMapper.insertCompanyMoneyLogs(log);
        }
    }

    @Override
    @Transactional
    public void subCompanyPaymentMoney(FsStorePaymentScrm payment) {
        Company company=companyMapper.selectCompanyByIdForUpdate(payment.getCompanyId());
        if(company!=null){
            company.setMoney(company.getMoney().subtract(payment.getRefundMoney()));
            company.setTuiMoney(company.getTuiMoney().subtract(payment.getRefundMoney()));
            companyMapper.updateCompany(company);
            //写入日志
            CompanyMoneyLogs log=new CompanyMoneyLogs();
            log.setCompanyId(payment.getCompanyId());
            log.setRemark("收款佣金退款");
            log.setMoney(payment.getRefundMoney().multiply(new BigDecimal(-1)));
            log.setLogsType(9);
            log.setBalance(company.getMoney());
            log.setCreateTime(new Date());
            log.setBusinessId(payment.getPaymentId().toString());
            moneyLogsMapper.insertCompanyMoneyLogs(log);
        }
    }

    @Override
    public String selectOmsCodeByCompanyId(Long companyId) {
        return companyMapper.selectOmsCodeByCompanyId(companyId);
    }

    @Override
    public void updateOmsCodeByCompanyIds(List<Long> companyIds, String omsCode) {
        for (Long companyId : companyIds){
            companyMapper.updateOmsCodeByCompanyIds(companyId,omsCode);
        }
    }

    @Override
    public List<Long> selectCompanyByOmsCode(String omsCode) {
        return companyMapper.selectCompanyByOmsCode(omsCode);
    }

    @Override
    public List<CompanyVO> selectCompanyListVO(Company company) {

        List<CompanyVO> companyVOList=companyMapper.selectCompanyListVO(company);
        companyVOList.forEach(companyVO -> {
            String redPackageMoney = redisCache.getCacheObject(FsConstants.COMPANY_MONEY_KEY+companyVO.getCompanyId());
            if(redPackageMoney!=null){
                companyVO.setRedPackageMoney(new BigDecimal(redPackageMoney));

            }
        });
        return companyVOList;
    }

    @Override
    @Transactional
    public void subtractCompanyMoney(FsStoreOrder order) {

        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
                StoreConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), StoreConfig.class);
                Integer DeductMoneyRate = fsPayConfig.getDeductMoneyRate();
                BigDecimal money = BigDecimal.ZERO;
                if (DeductMoneyRate != null && DeductMoneyRate > 0) {
                    money = order.getPrescribePrice().multiply(new BigDecimal(DeductMoneyRate).multiply(new BigDecimal("0.01")));
                }
                logger.info("扣除成本:"+order.getOrderCode()+":"+money);
                company.setMoney(company.getMoney().subtract(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("发货扣除成本");
                log.setMoney(money.multiply(new BigDecimal(-1)));
                log.setLogsType(5);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getOrderId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    @Override
    @Transactional
    public void subtractCompanyMoneyScrm(FsStoreOrderScrm order) {

        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
                StoreConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), StoreConfig.class);
                Integer DeductMoneyRate = fsPayConfig.getDeductMoneyRate();
                BigDecimal money = BigDecimal.ZERO;
                if (DeductMoneyRate != null && DeductMoneyRate > 0) {
                    money = order.getPrescribePrice().multiply(new BigDecimal(DeductMoneyRate).multiply(new BigDecimal("0.01")));
                }
                logger.info("扣除成本:"+order.getOrderCode()+":"+money);
                company.setMoney(company.getMoney().subtract(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("发货扣除成本");
                log.setMoney(money.multiply(new BigDecimal(-1)));
                log.setLogsType(5);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    @Override
    @Transactional
    public void inquirySubtractCompanyMoney(FsInquiryOrder order) {

        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                InquiryConfigDTO inquiryConfigDTO = JSON.parseObject(sysConfigMapper.selectConfigByConfigKey("his.inquiryConfig").getConfigValue(), InquiryConfigDTO.class);
                BigDecimal money = inquiryConfigDTO.getCompanyPrice();
                if(order.getInquiryType()==3){
                    money=inquiryConfigDTO.getCompanyPrescribePrice();
                }
                if (money!=null){
                    logger.info("扣除问诊费用:"+order.getOrderSn()+":"+money);
                    company.setMoney(company.getMoney().subtract(money));
                    companyMapper.updateCompany(company);
                    CompanyMoneyLogs log=new CompanyMoneyLogs();
                    log.setCompanyId(company.getCompanyId());
                    log.setRemark("扣除问诊费用");
                    log.setMoney(money.multiply(new BigDecimal(-1)));
                    log.setLogsType(12);
                    log.setBalance(company.getMoney());
                    log.setCreateTime(new Date());
                    log.setBusinessId(order.getOrderId().toString());
                    moneyLogsMapper.insertCompanyMoneyLogs(log);

                }

            }
        }
    }

    @Override
    @Transactional
    public void subtractCompanyMoney(BigDecimal money,Long companyId) {

        if(companyId!=null&&companyId>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(companyId);
            if(company!=null){
                logger.info("扣除红包金额:"+money);
                company.setMoney(company.getMoney().subtract(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("扣除昨日红包金额");
                log.setMoney(money.multiply(new BigDecimal(-1)));
                log.setLogsType(15);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    @Override
    public List<Long> selectCompanyIds() {
        return companyMapper.selectCompanyIds() ;
    }

    @Override
    public String selectCompanyByIds(String companyIds) {
        return companyMapper.selectCompanyNameCompanyByIds(companyIds);

    }

    @Override
    public List<DeptDataVO> getDeptData(Long companyId) {
        List<DeptDataVO> result = new ArrayList<>();

        // 获取用户按部门分组的数据
        Map<Long, List<CompanyUser>> companyUserGroupByDeptId = getCompanyUserGroupByDeptId();
        // 获取部门按公司分组的数据
        Map<Long, List<CompanyDept>> companyDeptGroupByCompanyId = getCompanyDeptGroupByCompanyId();
        // 获取子部门按父部门分组的数据
        Map<Long, List<CompanyDept>> deptGroupByParentId = getDeptGroupByParentId();

        if (companyId != null) {
            Company company = companyMapper.selectCompanyById(companyId);
            if (company != null) {
                DeptDataVO companyNode = buildCompanyNode(company, companyUserGroupByDeptId,
                        companyDeptGroupByCompanyId, deptGroupByParentId);
                result.add(companyNode);
            }
        } else {
            List<Company> companies = companyMapper.selectCompanyAllList();
            if (companies != null && !companies.isEmpty()) {
                for (Company company : companies) {
                    DeptDataVO companyNode = buildCompanyNode(company, companyUserGroupByDeptId,
                            companyDeptGroupByCompanyId, deptGroupByParentId);
                    result.add(companyNode);
                }
            }
        }

        return result.stream()
                .filter(e -> CollectionUtils.isNotEmpty(e.getChildren()))
                .collect(Collectors.toList());
    }

    @Autowired
    private CompanyUserRoleMapper companyUserRoleMapper;
    @Override
    public List<DeptDataVO> getDeptData(Long companyId, Long currentCompanyUserId, Long currentDeptId) {
        List<DeptDataVO> result = new ArrayList<>();
        // 线程中可能会残留的分页信息，这里清除，解决报错
        PageHelper.clearPage();
        Long isAdmin = companyUserRoleMapper.companyUserIsAdmin(currentCompanyUserId);
        logger.info("当前用户 {} 是公司admin 返回公司所有部门树",currentDeptId);
        if(isAdmin!=null){
            return getDeptData(companyId);
        }
        // 1. 获取所有部门数据
        List<CompanyDept> allCompanyDepts = companyDeptMapper.queryDeptDataAll();

        // 2. 按部门ID分组，方便直接获取部门信息
        Map<Long, CompanyDept> deptMapById = allCompanyDepts.stream()
                .filter(e -> e.getDeptId() != null)
                .collect(Collectors.toMap(CompanyDept::getDeptId, dept -> dept, (a, b) -> a));

        // 3. 按父部门ID分组，用于构建树结构
        Map<Long, List<CompanyDept>> deptsByParentIdMap = allCompanyDepts.stream()
                .filter(e -> e.getParentId() != null && e.getDeptId() != null)
                .collect(Collectors.groupingBy(CompanyDept::getParentId));

        // 4. 获取所有用户数据并按部门分组
        Map<Long, List<CompanyUser>> allUsersByDeptIdMap = getCompanyUserGroupByDeptId();

        // 5. 获取当前用户可见的部门ID集合（本部门及下级部门）
        Set<Long> visibleDeptIds = new HashSet<>();
        if (currentDeptId != null) {
            visibleDeptIds.add(currentDeptId); // 添加当前部门
            collectSubDepartments(currentDeptId, visibleDeptIds, deptsByParentIdMap); // 添加所有下级部门
        }

        // 6. 如果没有可见部门，直接返回空列表
        if (visibleDeptIds.isEmpty()) {
            return result;
        }

        // 7. 获取公司信息
        Company company = companyMapper.selectCompanyById(companyId);
        if (company == null) {
            return result;
        }

        // 8. 构建公司节点
        DeptDataVO companyNode = new DeptDataVO();
        companyNode.setLabel(company.getCompanyName());
        companyNode.setId("company_"+company.getCompanyId());

        // 9. 构建部门树（仅包含可见部门）
        // 先找到当前部门对象
        CompanyDept currentDept = deptMapById.get(currentDeptId);
        if (currentDept == null) {
            return result;
        }

        // 获取当前部门的所有上级部门路径
        List<Long> deptPath = new ArrayList<>();
        Long tempDeptId = currentDeptId;
        while (tempDeptId != null && tempDeptId > 0) {
            CompanyDept dept = deptMapById.get(tempDeptId);
            if (dept == null) break;
            deptPath.add(tempDeptId);
            tempDeptId = dept.getParentId();
        }

        // 构建以公司为根的树形结构
        // 找出顶级部门（parentId为null或0的部门）
        List<CompanyDept> rootDepts = allCompanyDepts.stream()
                .filter(dept -> dept.getCompanyId() != null &&
                        dept.getCompanyId().equals(companyId) &&
                        (dept.getParentId() == null || dept.getParentId().equals(0L)))
                .collect(Collectors.toList());

        // 递归构建带权限的树
        List<DeptDataVO> deptTree = buildDeptTreeWithPermission(
                rootDepts,
                allUsersByDeptIdMap,
                deptsByParentIdMap,
                visibleDeptIds,
                deptPath,
                currentDeptId,
                currentCompanyUserId);

        companyNode.setChildren(deptTree.isEmpty() ? null : deptTree);
        result.add(companyNode);

        // 过滤掉空公司节点
        return result.stream()
                .filter(node -> node.getChildren() != null && !node.getChildren().isEmpty())
                .collect(Collectors.toList());
    }
    /**
     * 递归收集所有下级部门ID
     */
    private void collectSubDepartments(Long parentDeptId, Set<Long> deptIds, Map<Long, List<CompanyDept>> deptsByParentIdMap) {
        List<CompanyDept> childDepts = deptsByParentIdMap.get(parentDeptId);
        if (childDepts != null && !childDepts.isEmpty()) {
            for (CompanyDept childDept : childDepts) {
                if (childDept.getDeptId() != null && deptIds.add(childDept.getDeptId())) {
                    collectSubDepartments(childDept.getDeptId(), deptIds, deptsByParentIdMap);
                }
            }
        }
    }
    /**
     * 递归构建带权限控制的部门树
     */
    private List<DeptDataVO> buildDeptTreeWithPermission(
            List<CompanyDept> depts,
            Map<Long, List<CompanyUser>> allUsersByDeptIdMap,
            Map<Long, List<CompanyDept>> deptsByParentIdMap,
            Set<Long> visibleDeptIds,
            List<Long> deptPath,
            Long currentDeptId,
            Long currentCompanyUserId) {

        if (depts == null || depts.isEmpty()) {
            return new ArrayList<>();
        }
        List<DeptDataVO> result = new ArrayList<>();
        for (CompanyDept dept : depts) {
            // 如果当前部门不在用户可见范围内，且不在部门路径中，则跳过
            if (!visibleDeptIds.contains(dept.getDeptId()) && !deptPath.contains(dept.getDeptId())) {
                continue;
            }

            // 先递归构建子部门
            List<CompanyDept> childDepts = deptsByParentIdMap.get(dept.getDeptId());
            List<DeptDataVO> children = new ArrayList<>();

            if (childDepts != null && !childDepts.isEmpty()) {
                List<DeptDataVO> childDeptNodes = buildDeptTreeWithPermission(
                        childDepts,
                        allUsersByDeptIdMap,
                        deptsByParentIdMap,
                        visibleDeptIds,
                        deptPath,
                        currentDeptId,
                        currentCompanyUserId);
                if (!childDeptNodes.isEmpty()) {
                    children.addAll(childDeptNodes);
                }
            }
            // 添加部门下的用户（需要权限控制）
            List<DeptDataVO> userNodes = new ArrayList<>();
            if (visibleDeptIds.contains(dept.getDeptId())) {
                List<CompanyUser> deptUsers = allUsersByDeptIdMap.get(dept.getDeptId());
                if (deptUsers != null && !deptUsers.isEmpty()) {
                    for (CompanyUser user : deptUsers) {
                        // 如果是当前部门，只显示当前用户
                        if (dept.getDeptId().equals(currentDeptId)) {
                            if (user.getUserId().equals(currentCompanyUserId)) {
                                DeptDataVO userNode = new DeptDataVO();
                                userNode.setLabel(user.getNickName() + "_" + user.getUserName());
                                userNode.setId("user_"+user.getUserId());
                                userNode.setChildren(null);
                                userNodes.add(userNode);
                            }
                        } else {
                            // 非当前部门，显示所有用户
                            DeptDataVO userNode = new DeptDataVO();
                            userNode.setLabel(user.getNickName() + "_" + user.getUserName());
                            userNode.setId("user_"+user.getUserId());
                            userNode.setChildren(null);
                            userNodes.add(userNode);
                        }
                    }
                }
            }

            // 将用户节点添加到子节点列表
            if (!userNodes.isEmpty()) {
                children.addAll(userNodes);
            }
            // 只有当下面有子部门或者有用户时，才添加此部门
            if (!children.isEmpty()) {
                DeptDataVO deptNode = new DeptDataVO();
                deptNode.setLabel(dept.getDeptName());
                deptNode.setId("dept_"+dept.getDeptId());
                deptNode.setChildren(children);
                result.add(deptNode);
            } else if (deptPath.contains(dept.getDeptId())) {
                // 即使没有子部门和用户，如果是部门路径上的节点，仍然需要添加
                DeptDataVO deptNode = new DeptDataVO();
                deptNode.setLabel(dept.getDeptName());
                deptNode.setId("dept_"+dept.getDeptId());
                deptNode.setChildren(null);
                result.add(deptNode);
            }
        }
        return result;
    }
    /**
     * 获取用户按部门ID分组
     */
    public Map<Long, List<CompanyUser>> getCompanyUserGroupByDeptId() {
        List<CompanyUser> userList = companyUserMapper.selectAllCompanyUserList();
        return userList.stream()
                .filter(user -> user.getDeptId() != null)
                .collect(Collectors.groupingBy(CompanyUser::getDeptId));
    }


    /**
     * 获取部门按公司ID分组
     */
    public Map<Long, List<CompanyDept>> getCompanyDeptGroupByCompanyId() {
        List<CompanyDept> companyDepts = companyDeptMapper.queryDeptDataAll();
        return companyDepts.stream()
                .collect(Collectors.groupingBy(CompanyDept::getCompanyId));
    }

    /**
     * 获取部门按父部门ID分组（新增方法）
     */
    public Map<Long, List<CompanyDept>> getDeptGroupByParentId() {
        List<CompanyDept> companyDepts = companyDeptMapper.queryDeptDataAll();
        return companyDepts.stream()
                .filter(dept -> dept.getParentId() != null) // 过滤掉顶级部门
                .collect(Collectors.groupingBy(CompanyDept::getParentId));
    }

    /**
     * 构建公司节点，包含其下属多级部门和用户
     */
    private DeptDataVO buildCompanyNode(Company company,
                                        Map<Long, List<CompanyUser>> companyUserGroupByDeptId,
                                        Map<Long, List<CompanyDept>> companyDeptGroupByCompanyId,
                                        Map<Long, List<CompanyDept>> deptGroupByParentId) {
        DeptDataVO companyNode = new DeptDataVO();
        companyNode.setLabel(company.getCompanyName());
        companyNode.setId("company_"+company.getCompanyId());

        // 获取公司下的顶级部门（parentId为null或为公司ID的部门）
        List<CompanyDept> topLevelDepts = companyDeptGroupByCompanyId.get(company.getCompanyId());
        if (topLevelDepts != null) {
            topLevelDepts = topLevelDepts.stream()
                    .filter(dept -> dept.getParentId() == null || dept.getParentId().equals(0L))
                    .collect(Collectors.toList());
        }

        List<DeptDataVO> deptDataList = buildDeptTree(topLevelDepts, companyUserGroupByDeptId, deptGroupByParentId);
        companyNode.setChildren(deptDataList.isEmpty() ? null : deptDataList);

        return companyNode;
    }

    /**
     * 递归构建部门树
     */
    private List<DeptDataVO> buildDeptTree(List<CompanyDept> depts,
                                           Map<Long, List<CompanyUser>> companyUserGroupByDeptId,
                                           Map<Long, List<CompanyDept>> deptGroupByParentId) {
        if (depts == null || depts.isEmpty()) {
            return new ArrayList<>();
        }

        List<DeptDataVO> result = new ArrayList<>();

        for (CompanyDept dept : depts) {
            DeptDataVO deptNode = new DeptDataVO();
            deptNode.setLabel(dept.getDeptName());
            deptNode.setId("dept_"+dept.getDeptId());

            List<DeptDataVO> children = new ArrayList<>();

            // 1. 添加子部门（递归）
            List<CompanyDept> childDepts = deptGroupByParentId.get(dept.getDeptId());
            if (childDepts != null && !childDepts.isEmpty()) {
                List<DeptDataVO> childDeptNodes = buildDeptTree(childDepts, companyUserGroupByDeptId, deptGroupByParentId);
                children.addAll(childDeptNodes);
            }

            // 2. 添加部门下的用户
            List<CompanyUser> deptUsers = companyUserGroupByDeptId.get(dept.getDeptId());
            if (deptUsers != null && !deptUsers.isEmpty()) {
                for (CompanyUser user : deptUsers) {
                    DeptDataVO userNode = new DeptDataVO();
                    userNode.setLabel(user.getNickName()+"_"+user.getUserName());
                    userNode.setId("user_"+user.getUserId());
                    userNode.setChildren(null);
                    children.add(userNode);
                }
            }

            deptNode.setChildren(children.isEmpty() ? null : children);
            result.add(deptNode);
        }

        return result;
    }

    @Override
    @Transactional
    public void refundCompanyMoney(FsStoreOrder order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                List<CompanyMoneyLogs> companyMoneyLogs = moneyLogsMapper.selectCompanyMoneyByOrderId(order.getOrderId());
                for (CompanyMoneyLogs logs : companyMoneyLogs) {
                    if (logs.getLogsType()==3){
                        if (order.getTuiMoneyStatus()!=null&&order.getTuiMoneyStatus()==0){
                            continue;
                        }
                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
                        logger.info("退款佣金扣除:"+company.getCompanyId()+":"+money);
                        company.setMoney(company.getMoney().subtract(logs.getMoney()));
                        companyMapper.updateCompany(company);
                        CompanyMoneyLogs log=new CompanyMoneyLogs();
                        log.setCompanyId(company.getCompanyId());
                        log.setRemark("退款佣金扣除");
                        log.setMoney(money);
                        log.setLogsType(4);
                        log.setBalance(company.getMoney());
                        log.setCreateTime(new Date());
                        log.setBusinessId(order.getOrderId().toString());
                        moneyLogsMapper.insertCompanyMoneyLogs(log);
                    }else if(logs.getLogsType()==5){
                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
                        logger.info("退款成本返还:"+company.getCompanyId()+":"+money);
                        company.setMoney(company.getMoney().add(money));
                        companyMapper.updateCompany(company);
                        CompanyMoneyLogs log=new CompanyMoneyLogs();
                        log.setCompanyId(company.getCompanyId());
                        log.setRemark("退款成本返还");
                        log.setMoney(money);
                        log.setLogsType(6);
                        log.setBalance(company.getMoney());
                        log.setCreateTime(new Date());
                        log.setBusinessId(order.getOrderId().toString());
                        moneyLogsMapper.insertCompanyMoneyLogs(log);
                    }
                }

            }
        }
    }

    @Override
    @Transactional
    public void refundCompanyMoneyScrm(FsStoreOrderScrm order) {
        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
            if(company!=null){
                List<CompanyMoneyLogs> companyMoneyLogs = moneyLogsMapper.selectCompanyMoneyByOrderId(order.getId());
                for (CompanyMoneyLogs logs : companyMoneyLogs) {
                    if (logs.getLogsType()==3){
                        if (order.getTuiMoneyStatus()!=null&&order.getTuiMoneyStatus()==0){
                            continue;
                        }
                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
                        logger.info("退款佣金扣除:"+company.getCompanyId()+":"+money);
                        company.setMoney(company.getMoney().subtract(logs.getMoney()));
                        companyMapper.updateCompany(company);
                        CompanyMoneyLogs log=new CompanyMoneyLogs();
                        log.setCompanyId(company.getCompanyId());
                        log.setRemark("退款佣金扣除");
                        log.setMoney(money);
                        log.setLogsType(4);
                        log.setBalance(company.getMoney());
                        log.setCreateTime(new Date());
                        log.setBusinessId(order.getId().toString());
                        moneyLogsMapper.insertCompanyMoneyLogs(log);
                    }else if(logs.getLogsType()==5){
                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
                        logger.info("退款成本返还:"+company.getCompanyId()+":"+money);
                        company.setMoney(company.getMoney().add(money));
                        companyMapper.updateCompany(company);
                        CompanyMoneyLogs log=new CompanyMoneyLogs();
                        log.setCompanyId(company.getCompanyId());
                        log.setRemark("退款成本返还");
                        log.setMoney(money);
                        log.setLogsType(6);
                        log.setBalance(company.getMoney());
                        log.setCreateTime(new Date());
                        log.setBusinessId(order.getId().toString());
                        moneyLogsMapper.insertCompanyMoneyLogs(log);
                    }
                }

            }
        }
    }

    @Override
    public Company selectCompanyByIdForUpdate(Long companyId) {
        return companyMapper.selectCompanyByIdForUpdate(companyId);
    }


    @Override
    public void configUserCheck(Long companyId, Integer userIsDefaultBlack) {
        Company company = companyMapper.selectCompanyById(companyId);
        if(company != null) {
            company.setFsUserIsDefaultBlack(userIsDefaultBlack);
            companyMapper.updateCompany(company);
        }
    }

    @Override
    @Transactional
    public void addRedPacketCompanyMoney(BigDecimal money, Long companyId) {
        if(companyId!=null&&companyId>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(companyId);
            if(company!=null){
                logger.info("退回红包金额:"+money);
                company.setMoney(company.getMoney().add(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                log.setRemark("退回红包金额");
                log.setMoney(money);
                log.setLogsType(16);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    @Override
    public List<CompanyUser> selectCompanyListByIds(String result) {
        return companyMapper.selectCompanyListByIds(result);
    }

    /**
     * 查询企微主体管理公司列表
     */
    @Override
    public List<OptionsVO> getCompanyListByCorpId(String corpId) {
        return companyMapper.getCompanyListByCorpId(corpId);
    }

    @Override
    @Transactional
    public void subtractCompanyMoneyHourse(BigDecimal money, Long companyId, LocalTime start, LocalTime end) {
        if(companyId!=null&&companyId>0){
            Company company=companyMapper.selectCompanyByIdForUpdate(companyId);
            if(company!=null){
                logger.info("每个小时扣除红包金额:{}", money);
                company.setMoney(company.getMoney().subtract(money));
                companyMapper.updateCompany(company);
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(company.getCompanyId());
                if(end != null && start.getHour() != end.getHour()){
                    log.setRemark("扣除"+start.getHour() + "到" + end.getHour() +"点红包金额");
                }else{
                    log.setRemark("扣除"+start.getHour()+"点红包金额");
                }
                log.setMoney(money.multiply(new BigDecimal(-1)));
                log.setLogsType(15);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
            }
        }
    }

    /**
     * @Description: 同步公司余额到数据库中
     * @Param:
     * @Return:
     * @Author xgb
     * @Date 2025/10/24 16:49
     */
    @Override
    public void syncCompanyBalance() {
        Company query = new Company();
        query.setIsDel(0);
        // 查询公司列表 同步公司余额
        List<Company> companyList = companyMapper.selectCompanyList(query);
        Optional.ofNullable(companyList)
                .ifPresent(list -> list.forEach(company -> {
                    try {
                        transactionTemplate.execute(status -> {
                            String moneyStr = redisCache.getCacheObject(FsConstants.COMPANY_MONEY_KEY + company.getCompanyId());
                            if (StringUtils.isNotEmpty(moneyStr)) {
                                BigDecimal redisMoney = new BigDecimal(moneyStr);
                                BigDecimal dbMoney = company.getRedPackageMoney();
                                BigDecimal amount = redisMoney.subtract(dbMoney); // 计算差额

                                // 只有当余额不一致时才更新
                                if (amount.compareTo(BigDecimal.ZERO) != 0) {
                                    company.setRedPackageMoney(redisMoney);
                                    int updateResult = companyMapper.updateCompany(company);
                                    if(updateResult != 1){
                                        logger.error("更新公司余额失败，公司ID: {}", company.getCompanyId());
                                        throw new RuntimeException("更新公司余额失败");
                                    }

                                    // 记录余额变更日志
                                    String remark = "同步公司余额，差额: " + amount+"(正数为增加，负数为扣减)";
                                    // 实际不发生交易只是从缓存同步金额到数据库中 交易金额登记为0，备注清楚同步的金额
                                    asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),17,redisMoney,remark);
                                }
                            }
                            return null;
                        });
                    } catch (Exception e) {
                        logger.error("同步公司余额失败，公司ID: {}", company.getCompanyId(), e);
                    }
                }));
    }

    /**
     * @Description: 红包充值
     * @Param: type 充值类型 1 充值 2 扣款
     * @Return:
     * @Author xgb
     * @Date 2025/11/3 14:01
     */
    @Override
    public void redPacketTopUpCompany(Long companyId, BigDecimal money,String type) {

        String companyMoneyKey = FsConstants.COMPANY_MONEY_KEY + companyId;

        // 加锁：增加余额
        RLock lock1 = redissonClient.getLock(FsConstants.COMPANY_MONEY_LOCK + companyId);
        boolean lockAcquired = false;
        try {
            if (lock1.tryLock(3, 10, TimeUnit.SECONDS)) {
                lockAcquired = true;
                BigDecimal originalMoney;
                // 获取当前余额
                String moneyStr = redisCache.getCacheObject(companyMoneyKey);
                if (StringUtils.isNotEmpty(moneyStr)) {
                    originalMoney = new BigDecimal(moneyStr);
                }else {
                    // 缓存没有值,重启系统恢复redis数据 保证数据正确性
                    logger.error("红包余额充值获取redis余额缓存异常，异常请求参数companyId：{}，money：{},type:{}",companyId,money, type);
                    throw new RuntimeException("红包余额充值获取redis余额缓存异常");
                }

                if(type.equals("1")){// 充值

                }else if(type.equals("2")) {// 扣减
                    money=money.multiply(new BigDecimal(-1));
                }else {
                    logger.error("红包余额充值参数异常，异常请求参数companyId：{}，money：{},type:{}",companyId,money, type);
                    throw new RuntimeException("红包余额充值参数异常");
                }
                // 增加余额
                BigDecimal newMoney = originalMoney.add(money);
                redisCache.setCacheObject(companyMoneyKey, newMoney.toString());

                // 异步登记余额添加日志
                asyncRecordBalanceLog(companyId,money,16,newMoney,"红包充值(负数为扣款)");

            } else {
                logger.error("获取redis锁失败，异常请求参数companyId：{}，money：{},type:{}",companyId,money, type);
                throw new RuntimeException("服务繁忙,请稍后重试");
            }
        } catch (Exception e) {
            logger.error("增加余额失败: 异常请求参数companyId：{}，money：{},type:{}",companyId,money, type, e);
            throw new RuntimeException("系统异常,请稍后重试");
        }finally {
            // 只有在成功获取锁的情况下才释放锁
            if (lockAcquired && lock1.isHeldByCurrentThread()) {
                try {
                    lock1.unlock();
                } catch (IllegalMonitorStateException e) {
                    logger.error("尝试释放非当前线程持有的锁: 异常请求参数companyId：{}，money：{},type:{}",companyId,money, type);
                }
            }
        }


    }


    /**
     * 异步登记余额添加日志  xgb
     * @param companyId 公司ID
     * @param money 变更金额
     * @param balance 当前余额
     * @param remark 备注信息
     * @param logType 16-红包余额充值 15-红包余额扣除 17-同步公司余额
     */
    @Async
    @Override
    public void asyncRecordBalanceLog(Long companyId, BigDecimal money,Integer logType, BigDecimal balance, String remark) {
        try {
            CompanyMoneyLogs log = new CompanyMoneyLogs();
            log.setCompanyId(companyId);
            log.setRemark(remark);
            log.setMoney(money);
            log.setLogsType(logType); // 同步余额
            log.setBalance(balance);
            log.setCreateTime(new Date());
            moneyLogsMapper.insertCompanyMoneyLogs(log);
            logger.info("异步登记余额日志成功 - 公司ID: {}, 金额: {}, 余额: {}, 备注: {}",
                    companyId, money, balance, remark);
        } catch (Exception e) {
            logger.error("异步登记余额日志失败 - 公司ID: {}, 金额: {}, 余额: {}, 备注: {}",
                    companyId, money, balance, remark, e);
        }
    }

    /**
     * @Description: 每天晚上0点定时获取获取公司余额，记录到数据库中
     * @Param:
     * @Return:
     * @Author xgb
     * @Date 2025/11/4 10:51
     */
    @Override
    public void recordRedPacketBalance() {
        Company query = new Company();
        query.setIsDel(0);
        // 查询公司列表 同步公司余额
        List<Company> companyList = companyMapper.selectCompanyList(query);
        Optional.ofNullable(companyList).ifPresent(list -> list.forEach(company -> {
            transactionTemplate.execute(status -> {
                String time=DateUtils.getTime();
                String moneyStr = redisCache.getCacheObject(FsConstants.COMPANY_MONEY_KEY + company.getCompanyId());
                if (StringUtils.isNotEmpty(moneyStr)) {
                    // 存到缓存中，有效期25小时
                    redisCache.setCacheObject(FsConstants.COMPANY_MONEY_DATE_KEY + company.getCompanyId()+":"+DateUtils.getDate(), moneyStr, 25, TimeUnit.HOURS);
                    // 实际不发生交易只是从缓存获取当天余额报错25小时 交易金额登记为0，备注清楚同步的金额
                    String remark = "时间:" + time +",当前公司余额，金额: " + moneyStr;
                    BigDecimal money = new BigDecimal(moneyStr);
                    asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),18,money,remark);
                }
                return null;
            });


        }));


    }


    @Override
    public void batchUpdateCompany(List<Company> list) {
        companyMapper.batchUpdateCompany(list);
    }

    /**
     * @Description: 红包余额回滚（回滚的是客户没领取的红包），红包记录表中，两天没领取的记录不会再发送
     * @Param:
     * @Return:
     * @Author xgb
     * @Date 2025/11/7 9:53
     */
    @Override
    public void rollbackRedPacketMoney() {
        List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseAddRedPacketLogByCompany();
        for(RedPacketMoneyVO company:redPacketMoneyVOS){
            logger.info("红包余额回滚开始：{}",company);
        }
        Optional.ofNullable(redPacketMoneyVOS).ifPresent(list -> list.forEach(company -> {

            if(company.getCompanyId()==null){
                logger.error("红包记录表中存在公司id为null的异常数据");
                return;
            }
            String companyMoneyKey = FsConstants.COMPANY_MONEY_KEY + company.getCompanyId();
            // 加锁，与看课发放红包的加锁保持一致
            RLock lock = redissonClient.getLock(FsConstants.COMPANY_MONEY_LOCK + company.getCompanyId());
            boolean lockAcquired = false;
            try {
                lockAcquired = lock.tryLock(3, 10, TimeUnit.SECONDS);
                if (lockAcquired) {
                    BigDecimal redisMoney;
                    // 获取当前余额
                    String moneyStr = redisCache.getCacheObject(companyMoneyKey);
                    if (StringUtils.isNotEmpty(moneyStr)) {
                        redisMoney = new BigDecimal(moneyStr);
                    }else {
                        logger.error("缓存公司id:{}的余额不存在,回滚金额{}",company.getCompanyId(),company.getMoney());
                        return;
                    }
                    BigDecimal newMoney = redisMoney.add(company.getMoney());
                    redisCache.setCacheObject(companyMoneyKey, newMoney.toString());

                    String remark = "执行时间:"+DateUtils.getTime()+"，T2天客户未领取红包退回，金额: " + company.getMoney();
                    asyncRecordBalanceLog(company.getCompanyId(),company.getMoney(),16,newMoney,remark);
                }
            } catch (Exception e) {
                logger.error("退回的红包同步增加到缓存和数据表，参数错误，请求异常，异常信息：{}", e.getMessage(), e);
            } finally {
                if (lockAcquired && lock.isHeldByCurrentThread()) {
                    try {
                        lock.unlock();
                    } catch (IllegalMonitorStateException e) {
                        logger.warn("尝试释放非当前线程持有的锁: companyId：{}", company.getCompanyId());
                    }
                }
            }
        }));
    }

}
