package com.ytpm.typing.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ytpm.advertise.enums.AdSourceTypeEnum;
import com.ytpm.agent.enums.UserStatusEnum;
import com.ytpm.agent.param.AuditCheckParam;
import com.ytpm.agent.param.AuditUserParam;
import com.ytpm.agent.view.AgentAuditCheckVO;
import com.ytpm.app.model.YtDyzAdRecord;
import com.ytpm.app.model.YtDyzLoginRecord;
import com.ytpm.app.model.YtDyzUser;
import com.ytpm.app.param.*;
import com.ytpm.app.view.HourCountView;
import com.ytpm.app.view.YtAppUserListView;
import com.ytpm.feign.RiskFeign;
import com.ytpm.general.RepMessage;
import com.ytpm.general.Result;
import com.ytpm.general.ResultTable;
import com.ytpm.general.StatusCode;
import com.ytpm.typing.dao.AdRecordMapper;
import com.ytpm.typing.dao.AppUserMapper;
import com.ytpm.typing.dao.LoginRecordMapper;
import com.ytpm.typing.dao.QuestionMapper;
import com.ytpm.typing.redis.RedisService;
import com.ytpm.risk.enums.BannedTypeEnum;
import com.ytpm.risk.view.RiskConfigView;
import com.ytpm.risk.view.RiskTemplateView;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private AppUserMapper appUserMapper;
    @Autowired
    private LoginRecordMapper loginRecordMapper;
    @Autowired
    private AdRecordMapper adRecordMapper;
    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RiskFeign riskFeign;
    /**
     * 根据应用ID查询当月注册用户
     */
    @GetMapping("/getMonthRegistryUser")
    public List<YtDyzUser> getMonthRegistryUser(@RequestParam("appIds")String appIds, @RequestParam("type")Integer type) {
        return appUserMapper.getMonthRegistryUser(appIds,type);
    }
    /**
     * 查询app 所有玩家
     *  汇聚分库应用
     */
    @PostMapping("/queryAll")
    public ResultTable<YtAppUserListView> queryAll(@RequestBody YtAppUserListParam param) {
        //查询主应用
        PageHelper.startPage(param.getPage(), param.getLimit());
        List<YtAppUserListView> result = appUserMapper.queryAll(param);
        String collect = result.stream().map(YtAppUserListView::getUserId).collect(Collectors.joining(","));
        List<YtDyzAdRecord> adRecords = adRecordMapper.getByUserIds(collect);
        List<YtDyzLoginRecord> dyzLogins = loginRecordMapper.getLoginRecordByIds(collect);
        Map<String, List<YtDyzAdRecord>> userAdMap = adRecords.stream().collect(
                Collectors.groupingBy(YtDyzAdRecord::getUserId));
        Map<String, List<YtDyzLoginRecord>> loginMap = dyzLogins.stream().collect(
                Collectors.groupingBy(YtDyzLoginRecord::getUserId));
        setUserExtInfo(result,userAdMap,loginMap);
        return ResultTable.resultTableOk(new PageInfo<>(result));
    }

    /**
     * 设置视频记录和登录信息
     */
    private void setUserExtInfo(List<YtAppUserListView> result, Map<String, List<YtDyzAdRecord>> userAdMap,Map<String, List<YtDyzLoginRecord>> loginMap) {
        for (YtAppUserListView user : result) {
            if(loginMap.containsKey(user.getUserId())){
                user.setLoginRecordList(loginMap.get(user.getUserId()));
            }
            //获取今日收益 | 今日视频播放数
            if (userAdMap.containsKey(user.getUserId())) {
                List<YtDyzAdRecord> ytDyzAdRecords = userAdMap.get(user.getUserId());
                List<YtDyzAdRecord> collect = ytDyzAdRecords.stream().filter(
                        s -> DateUtil.isSameDay(DateUtil.date(),DateUtil.parseDate(s.getFinishTime()))).collect(Collectors.toList());
                BigDecimal todayIncome = collect.stream().map(YtDyzAdRecord::getRevenue).reduce(BigDecimal.ZERO, BigDecimal::add);
                user.setTodayVideo((int) collect.stream().filter(
                        s->s.getAdSourceType()== AdSourceTypeEnum.rewarded_video.getAdSourceType()).count());
                user.setTodayIncome(todayIncome);
            } else {
                user.setTodayIncome(BigDecimal.ZERO);
                user.setTodayVideo(0);
            }
        }
    }

    /**
     * 根据时间统计收益
     */
    @PostMapping("/getRevenueByTime")
    public BigDecimal getRevenueByTime(@RequestBody YtAppUserListParam param) {
        BigDecimal result = new BigDecimal(0);
        BigDecimal dyzRevenue = adRecordMapper.getRevenueByTime(param);
        if(Objects.nonNull(dyzRevenue)){
            result = result.add(dyzRevenue);
        }
        return result;
    }


    /**
     * 主键查询用户信息
     */
    @GetMapping("/getUserInfo")
    public Result<YtDyzUser> getUserInfo(@RequestParam("userId") String userId) {
        YtDyzUser user = appUserMapper.selectPrimaryKey(userId);
        user.setLoginRecordList(loginRecordMapper.getLoginRecords(userId));
        user.setTodayAnswerCount(questionMapper.getAnswerCount(userId,1));
        user.setHistoryAnswerCount(questionMapper.getAnswerCount(userId,2));
        user.setAnswerRecordList(questionMapper.getAnswerRecords(userId));
        Result<?> result = riskFeign.checkAdRisk(user);
        if (result != null) {
            user.setIfPowerLimit(false);
            if (result.getCode() != 200) {
                if ("766".equals(result.getMessage()) || result.getCode() == StatusCode.ACCESS_RISK_ERROR && StrUtil.isNotEmpty(result.getMessage())) {
                    user.setIfPowerLimit(true);
                }
            }
        }
        return Result.resultObjOk(user);
    }

    /**
     * 查询用户信息
     */
    @PostMapping("/getUserList")
    public ResultTable<YtDyzUser> getUserList(@RequestBody AppUserParam param) {
        List<YtDyzUser> resultList = new ArrayList<>();
        List<YtDyzUser> userList = appUserMapper.getUserList(param);
        if(CollUtil.isNotEmpty(userList)){resultList.addAll(userList);}
        return ResultTable.resultTableOk(new PageInfo<>(resultList));
    }

    @PostMapping("/getUserAll")
    public ResultTable<YtDyzUser> getUserAll(@RequestBody AppUserParam param) {
        List<YtDyzUser> userList = appUserMapper.getUserList(param);
        return ResultTable.resultTableOk(new PageInfo<>(userList));
    }

    /**
     * 修改用户信息
     */
    @PostMapping("/updateUserInfo")
    public Result<?> updateUserInfo(@RequestBody YtDyzUser dyzUser) {
        appUserMapper.updateUser(dyzUser);
        return Result.resultOk(RepMessage.MODIFY_SUCCESS);
    }

    /**
     * 查询用户的广告记录
     */
    @GetMapping("/adRecords")
    public ResultTable<YtDyzAdRecord> adRecords(@RequestParam(name = "userId",required = true) String userId,@RequestParam(name = "adsourceType",required = false)Integer adsourceType) {
        List<YtDyzAdRecord> result = new ArrayList<>();
        List<YtDyzAdRecord> adrecords = adRecordMapper.getByUserId(userId, adsourceType);
        if(CollUtil.isNotEmpty(adrecords)){
            result.addAll(adrecords);
        }
        return ResultTable.resultTableOk(new PageInfo<YtDyzAdRecord>(result));
    }

    @PostMapping("/queryUserByTime")
    public List<YtDyzUser> queryUserByTime(@RequestBody AppUserQueryParam appUserQueryParam) {
        List<YtDyzUser> ytDyzUsers = appUserMapper.queryAllByTime(appUserQueryParam.getStartTime(), appUserQueryParam.getEndTime(),appUserQueryParam.getAppIdList());
        return ytDyzUsers;
    }

    @PostMapping("/queryUserByTodayTime")
    public int[] queryUserByTodayTime(@RequestBody AppQueryUserTodayTimeParam appQueryUserTodayTimeParam) {
        // 获取当前日期
        LocalDate localDate = LocalDate.now();

        // 构建当天起始时间段
        LocalDateTime startOfDay = localDate.atStartOfDay();
        LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);

        Date startTime = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
        Date endTime = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
        // 查询用户注册数据
        List<HourCountView> hourCountViews = appUserMapper.countUsersByHour(startTime, endTime,appQueryUserTodayTimeParam.getAppIdList());
        // 初始化每小时用户数量数组
        int[] hourlyCounts = new int[24];
        for (HourCountView hc : hourCountViews) {
            if (hc.getHour() >= 0 && hc.getHour() < 24) {
                hourlyCounts[hc.getHour()] = hc.getCount();
            }
        }
        return hourlyCounts;
    }

    @PostMapping("/queryLoginRecords")
    public List<String> queryLoginRecords(@RequestBody AppUserQueryParam appUserQueryParam) {
        return loginRecordMapper.queryLoginCount(appUserQueryParam);
    }

    @GetMapping("/queryByOpenid")
    public List<YtDyzUser> queryByOpenid(@RequestParam("openid") String openid){
        return appUserMapper.queryByOpenid(openid);
    }
    @PostMapping("/queryTodayBanned")
    public List<YtDyzUser> queryTodayBanned(@RequestBody AppUserTodayBannedParam appUserTodayBannedParam){
        return appUserMapper.queryTodayBanned(appUserTodayBannedParam.getStartTime(), appUserTodayBannedParam.getEndTime(), appUserTodayBannedParam.getUserIdList());
    }
    @PostMapping("/unLockUser")
    public void unLockUser(@RequestParam("userIds")String userIds){
        List<YtDyzUser> dyzUsers = appUserMapper.queryByUserIds(userIds);
        if(CollUtil.isNotEmpty(dyzUsers)){
            appUserMapper.unlockUser(userIds);
            return;
        }
    }
    @GetMapping("/lockUser")
    public YtDyzUser lockUser(@RequestParam("userId")String userId,@RequestParam("userStatus")Integer userStatus){
        YtDyzUser dyzUser = appUserMapper.selectPrimaryKey(userId);
        YtDyzUser newUser = new YtDyzUser();
        newUser.setUserId(userId);
        newUser.setUserStatus(userStatus);
        newUser.setRiskReason(BannedTypeEnum.CHANNEL.getDesc()+"禁止登录");
        if(Objects.nonNull(dyzUser)){
            appUserMapper.updateUser(newUser);
            return dyzUser;
        }
        return null;
    }

    /**
     * 批量审核用户是否满足风控规则
     * 不满足风控规则的审核通过后直接封禁指定天数
     */
    @PostMapping("/batchAudit")
    public void batchAudit(@RequestBody AuditCheckParam checkParam){
        AuditUserParam auditParam = checkParam.getAuditParam();
        RiskTemplateView ecpmLimit = checkParam.getEcpmLimit();
        RiskTemplateView revenueLimit = checkParam.getRevenueLimit();
        //查询用户，指定应用激励视频的广告记录
        List<AgentAuditCheckVO> auditList = new ArrayList<>();
        List<AgentAuditCheckVO> auditCheckList = appUserMapper.queryTodayUserAd(auditParam);
        if(CollUtil.isNotEmpty(auditCheckList)){auditList.addAll(auditCheckList);}
        Map<String, List<YtDyzAdRecord>> adRecordMap = auditList.stream().collect(
                Collectors.toMap(AgentAuditCheckVO::getUserId, AgentAuditCheckVO::getAdRecordList));
        checkRisk742(ecpmLimit,adRecordMap,auditParam);
        checkRisk746(revenueLimit,adRecordMap,auditParam);
    }

    /**
     * 校验默认风控规则742
     */
    private void checkRisk742(RiskTemplateView ecpmLimit,Map<String, List<YtDyzAdRecord>> adRecordMap,AuditUserParam auditParam) {
        if(ecpmLimit.getEnabled()!=1)return;
        Map<String, String> limitMap = ecpmLimit.getConfigList().stream().collect(
                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
        int adCount = 0;
        for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
            adCount = CollUtil.isEmpty(entry.getValue())?adCount:entry.getValue().size();
            ++adCount;
            //判断当日观看视频数已经达到风控条件预设的视频数
            int firstAdCount = Integer.parseInt(limitMap.get("firstAdCount"));
            if(adCount>=firstAdCount){
                //过滤出ecpm值小于预设值的视频数
                int ecpm = Integer.parseInt(limitMap.get("ecpm"));
                long count = entry.getValue().stream().filter(
                        s -> Objects.nonNull(s.getEcpm())&&(s.getEcpm().compareTo(BigDecimal.valueOf(ecpm))) < 0).count();
                int exact = Math.toIntExact(count);
                //判断小于预设值的视频数超出预设次数
                int haveCount = Integer.parseInt(limitMap.get("haveCount"));
                if(exact>haveCount){//把风控不满足的用户记录redis 进行封禁
                    checkLock(entry,auditParam);
                }
            }
        }

    }

    /**
     * 用户锁定操作
     */
    private void checkLock(Map.Entry<String, List<YtDyzAdRecord>> entry, AuditUserParam auditParam) {
        log.error("执行对低价值用户{}的定时风控操作", entry.getKey());
        if(auditParam.getEffectTime() == 0){ //立即锁定
            lockUser(entry.getKey(), UserStatusEnum.RISK.getCode());
            redisService.setTimeOutHoursStr("unlock_"+entry.getKey(),auditParam.getAppId(), auditParam.getBannedLimit()*24L);
        }else{//延迟锁定
            redisService.setTimeOutHoursStr("lock_"+entry.getKey(), auditParam.getAppId(), auditParam.getEffectTime());
            redisService.setTimeOutHoursStr("unlock_"+entry.getKey(),auditParam.getAppId(),
                    auditParam.getBannedLimit()*24L + auditParam.getEffectTime());
        }
    }

    /**
     * 校验默认风控规则746
     */
    private void checkRisk746(RiskTemplateView revenueLimit,Map<String, List<YtDyzAdRecord>> adRecordMap,AuditUserParam auditParam) {
        if(revenueLimit.getEnabled()!=1)return;
        Map<String, String> revenueMap = revenueLimit.getConfigList().stream().collect(
                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
        for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
            List<YtDyzAdRecord> revenues = entry.getValue().stream().filter(
                    s -> Objects.nonNull(s.getRevenue())&&(s.getRevenue().compareTo(BigDecimal.ZERO)) > 0).collect(Collectors.toList());
            int incomeCount = 0;
            incomeCount = CollUtil.isEmpty(revenues)?incomeCount:entry.getValue().size();
            //判断当日获得收益的广告达到预设数值，触发风控规则
            int rewardCount = Integer.parseInt(revenueMap.get("rewardCount"));
            if(incomeCount>=rewardCount){
                BigDecimal income = new BigDecimal(revenueMap.get("income"));
                //获取最先的两条
                BigDecimal reduce = revenues.stream().map(YtDyzAdRecord::getRevenue).reduce(BigDecimal.ZERO, BigDecimal::add);
                if(reduce.compareTo(income)<0){
                    checkLock(entry,auditParam);
                }
            }
        }

    }
}
