package com.fs.company.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.core.redis.RedisCache;
import com.fs.company.constant.CompanyTrafficConstants;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyTrafficRecord;
import com.fs.company.domain.CompanyTrafficRecordLog;
import com.fs.company.mapper.CompanyTrafficRecordMapper;
import com.fs.company.param.CompanyTrafficRecordChargeParam;
import com.fs.company.param.CompanyTrafficRecordQueryParam;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyTrafficRecordLogService;
import com.fs.company.service.ICompanyTrafficRecordService;
import com.fs.course.mapper.FsCourseTrafficLogMapper;
import com.fs.system.domain.SysConfig;
import com.fs.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class CompanyTrafficRecordServiceImpl extends ServiceImpl<CompanyTrafficRecordMapper, CompanyTrafficRecord> implements ICompanyTrafficRecordService {

    @Autowired
    RedisCache redisCache;

    @Autowired
    private ISysConfigService iSysConfigService;

    @Autowired
    private ICompanyService companyService;

    private SysConfig config;

    @Autowired
    private ICompanyTrafficRecordLogService companyTrafficRecordLogService;

    @Autowired
    private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;

    //启动时初始化部门流量缓存
    @Override
    public void init() {
        List<CompanyTrafficRecord> companyTrafficRecords = baseMapper.selectList(new LambdaQueryWrapper<>());
        Map<Long,Long> deptTrafficMap = new HashMap<>();
        for (CompanyTrafficRecord companyTrafficRecord : companyTrafficRecords) {
            // 获取公司ID
            Long companyId = companyTrafficRecord.getCompanyId();
            // 部门ID
            Long deptId = companyService.selectCompanyById(companyId).getDeptId();
            companyTrafficRecord.setDeptId(deptId);

            // 公司流量 - 消耗流量
            Long balance = companyTrafficRecord.getBalance();
            //消耗的流量
            Long totalInternetTraffic = fsCourseTrafficLogMapper.sumTrafficByCompany(companyId) == null?0L:fsCourseTrafficLogMapper.sumTrafficByCompany(companyId);
            balance -= totalInternetTraffic;
            //部门流量记录
            Long deptTrafficAdd = (deptTrafficMap.get(deptId) == null ? 0L : deptTrafficMap.get(deptId)) + totalInternetTraffic;
            deptTrafficMap.put(deptId, deptTrafficAdd);
            //更新缓存
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId);
            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId, balance);
            //删除前天流量缓存(如果存在；保留两天)
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId + ":" + LocalDate.now().minusDays(2));
            //删除上上个月流量缓存
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId + ":" + YearMonth.now().minusMonths(2));
        }

        // 缓存 key=CACHE_KEY:deptId  value=部门ID
        calculateTotalTrafficByDeptId(deptTrafficMap);
    }

    @Override
    public void refreshTraffic() {
        log.info("【定时更新流量】：{}", "开始");
        List<CompanyTrafficRecord> companyTrafficRecords = baseMapper.selectList(new LambdaQueryWrapper<>());
        for (CompanyTrafficRecord companyTrafficRecord : companyTrafficRecords) {
            doReduce(companyTrafficRecord,"1");
        }
    }

    //通过redis更新表流量并添加扣除日志
    private void doReduce(CompanyTrafficRecord companyTrafficRecord, String doType) {

        //根据fs_course_traffic_log表获取公司昨天流量
        Long trafficAmountYesterday = fsCourseTrafficLogMapper.sumTrafficByCompanyYesterday(companyTrafficRecord.getCompanyId());
        if(trafficAmountYesterday!=null) {
            long balance = companyTrafficRecord.getBalance() - trafficAmountYesterday;
            companyTrafficRecord.setBalance(balance);
            log.info("【更新流量】：{}", "部门ID:" + companyTrafficRecord.getDeptId() +"公司ID:" + companyTrafficRecord.getCompanyId() +  "消耗流量:" + trafficAmountYesterday+"剩余流量:"+balance);
            if (trafficAmountYesterday > 0) {
                baseMapper.updateById(CompanyTrafficRecord.builder()
                        .id(companyTrafficRecord.getId())
                        .balance(balance)
                        .updateTime(new Date())
                        .updateBy(1L).build());
                companyTrafficRecordLogService.save(CompanyTrafficRecordLog.builder()
                        .balance(balance)
                        .trafficAmount(trafficAmountYesterday)
                        .companyId(companyTrafficRecord.getCompanyId())
                        .createTime(new Date())
                        .operationType(2)
                        .userId(1L)//表示amdin
                        .remark("0".equals(doType)?"重启同步流量":"定时更新扣除流量")
                        .userName("admin")
                        .build());
            }
        }
        init();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recharge(CompanyTrafficRecordChargeParam record) {
        CompanyTrafficRecord companyTrafficRecord = new CompanyTrafficRecord();
        //校验参数companyId
        if (record.getCompanyId() == null || !validCompany(record))
            throw new IllegalArgumentException("销售公司异常");

        //查询公司流量记录
        CompanyTrafficRecord companyRecord = baseMapper.selectOne(new LambdaQueryWrapper<CompanyTrafficRecord>()
                .eq(CompanyTrafficRecord::getCompanyId, record.getCompanyId()));

        //充值
        if (record.getOperationType() == 1) {//获取转换后的流量
            Long trafficAmount = trafficConversion(record.getChargeAmount());
            record.setChangeTraffic(trafficAmount);//用于处理日志
            if (companyRecord != null) {
                //不是第一次充值  增加流量
                companyTrafficRecord.setBalance(companyRecord.getBalance() + trafficAmount);
                companyTrafficRecord.setId(companyRecord.getId());
                companyTrafficRecord.setUpdateTime(new Date());
                companyTrafficRecord.setUpdateBy(record.getUserId());
                baseMapper.updateById(companyTrafficRecord);
            } else {
                companyTrafficRecord.setBalance(trafficAmount);
                companyTrafficRecord.setCompanyId(record.getCompanyId());
                companyTrafficRecord.setDeptId(record.getCompany().getDeptId());
                companyTrafficRecord.setCompanyName(record.getCompany().getCompanyName());
                companyTrafficRecord.setCreateTime(new Date());
                companyTrafficRecord.setCreateBy(record.getUserId());
                baseMapper.insert(companyTrafficRecord);
            }
                /*//扣除
            case 2:
                //扣除流量
                *//*if (companyRecord.getBalance() < record.getChangeTraffic())
                    throw new IllegalArgumentException("公司流量余额不足");*//*
                companyTrafficRecord.setBalance(companyTrafficRecord.getBalance() - record.getChangeTraffic());
                companyTrafficRecord.setId(companyRecord.getId());
                companyTrafficRecord.setUpdateTime(new Date());
                companyTrafficRecord.setUpdateBy(record.getUserId());
                baseMapper.updateById(companyTrafficRecord);
                break;*/
        } else {
            throw new IllegalArgumentException("非法的操作类型");
        }
        // 更新Redis缓存
        doRefresh(record, companyTrafficRecord);

        return doLog(companyTrafficRecord, record);
    }

    private boolean validCompany(CompanyTrafficRecordChargeParam record) {
        Company company = new Company();
        company.setCompanyId(record.getCompanyId());
        company.setIsDel(0);
        List<Company> companies = companyService.selectCompanyList(company);
        if (companies != null && companies.size() == 1) {
            record.setCompany(companies.get(0));
            return true;
        } else {
            return false;
        }
    }
    /**
     * 更新Redis缓存
     * @param record               充值参数
     * @param companyTrafficRecord 公司流量记录
     */
    private void doRefresh(CompanyTrafficRecordChargeParam record, CompanyTrafficRecord companyTrafficRecord) {
        if (record.getCompany() != null && record.getCompany().getDeptId() != null) {
            // 更新缓存 key=CACHE_KEY:deptId:companyId  value=剩余流量
            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + record.getCompany().getDeptId() + ":" + record.getCompanyId(),
                    companyTrafficRecord.getBalance());

            // 部门新增流量
            calculateTrafficByDeptId(record.getCompany().getDeptId(),companyTrafficRecord.getBalance());
        } else {
            // 抛出异常
            throw new IllegalArgumentException("缓存ID异常");
        }
    }
    /**
     * 部门下所有公司流量总和减去使用的流量
     */
    private void calculateTrafficByDeptId(Long deptId,Long traffic) {
        redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId, traffic);
    }

    /**
     * 部门下所有公司流量总和减去使用的流量
     */
    private void calculateTotalTrafficByDeptId(Map<Long,Long> deptTrafficMap) {
        deptTrafficMap.forEach((deptId,totalTraffic) -> {
            Long total = baseMapper.calculateTotalTrafficByDeptId(deptId);
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId);
            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId, total-totalTraffic);
            //删除前天缓存
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + LocalDate.now().minusDays(2));
            //删除上上月缓存
            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + YearMonth.now().minusMonths(2));
        });
    }

    private boolean doLog(CompanyTrafficRecord companyTrafficRecord, CompanyTrafficRecordChargeParam record) {
        return companyTrafficRecordLogService.save(CompanyTrafficRecordLog.builder()
                .balance(companyTrafficRecord.getBalance())
                .trafficAmount(record.getChangeTraffic())
                .chargeAmount(record.getChargeAmount())
                .companyId(record.getCompanyId())
                .createTime(new Date())
                .operationType(record.getOperationType())
                .userId(record.getUserId())
                .remark(record.getRemark())
                .userName(record.getUserName())
                .build());
    }

    @Override
    public List<CompanyTrafficRecord> selectList(CompanyTrafficRecordQueryParam record) {
        return baseMapper.selectListWithUncharged(record);
    }

    @Override
    public CompanyTrafficRecord selectById(Long id) {
        return baseMapper.selectById(id);
    }


    /**
     * 充值金额转换流量KB
     */
    @Override
    public Long trafficConversion(Long amount) {
        if (this.config == null) {
            this.config = iSysConfigService.selectConfigByConfigKey("statis.config");
        }
        JSONObject jsonObject = JSONObject.parseObject(this.config.getConfigValue());
        float trafficPrice = jsonObject.getFloatValue("trafficPrice");
        double trafficGB = amount / trafficPrice;
        return (long) (trafficGB * 1024 * 1024);
    }

    @Override
    public void refreshPrice() {
        this.config = iSysConfigService.selectConfigByConfigKey("statis.config");
    }
}
