package com.fs.statis.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.cache.ICompanyUserCacheService;
import com.fs.company.domain.CompanyDept;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyDeptMapper;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.course.domain.FsUserCoursePeriod;
import com.fs.course.mapper.FsUserCoursePeriodMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.sop.domain.QwSop;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.SopUserLogsMapper;
import com.fs.statis.domain.FsStatisSalerWatch;
import com.fs.statis.dto.StatsWatchLogPageListDTO;
import com.fs.statis.mapper.FsStatisSalerWatchMapper;
import com.fs.statis.service.FsStatisSalerWatchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 销售观看统计服务实现类
 */
@Service("fsStatisSalerWatchService")
@Slf4j
public class FsStatisSalerWatchServiceImpl implements FsStatisSalerWatchService {

    private final FsStatisSalerWatchMapper fsStatisSalerWatchMapper;

    private final CompanyUserMapper companyUserMapper;

    private final QwUserMapper qwUserMapper;

    private final QwSopLogsMapper qwSopLogsMapper;

    private final FsUserCoursePeriodMapper fsUserCoursePeriodMapper;

    private final QwSopMapper qwSopMapper;

    private final SopUserLogsMapper sopUserLogsMapper;

    private final CompanyDeptMapper companyDeptMapper;

    private final ICompanyUserCacheService companyUserCacheService;


    @Autowired
    public FsStatisSalerWatchServiceImpl(FsStatisSalerWatchMapper fsStatisSalerWatchMapper, CompanyUserMapper companyUserMapper, QwUserMapper qwUserMapper, QwSopLogsMapper qwSopLogsMapper, FsUserCoursePeriodMapper fsUserCoursePeriodMapper, QwSopMapper qwSopMapper, SopUserLogsMapper sopUserLogsMapper, CompanyDeptMapper companyDeptMapper, ICompanyUserCacheService companyUserCacheService) {
        this.fsStatisSalerWatchMapper = fsStatisSalerWatchMapper;
        this.companyUserMapper = companyUserMapper;
        this.qwUserMapper = qwUserMapper;
        this.qwSopLogsMapper = qwSopLogsMapper;
        this.fsUserCoursePeriodMapper = fsUserCoursePeriodMapper;
        this.qwSopMapper = qwSopMapper;
        this.sopUserLogsMapper = sopUserLogsMapper;
        this.companyDeptMapper = companyDeptMapper;
        this.companyUserCacheService = companyUserCacheService;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FsStatisSalerWatch getById(Integer id) {
        if (id == null) {
            return null;
        }
        return fsStatisSalerWatchMapper.findById(id);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<FsStatisSalerWatch> getAll() {
        return fsStatisSalerWatchMapper.findAll();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FsStatisSalerWatch create(FsStatisSalerWatch fsStatisSalerWatch) {
        if (fsStatisSalerWatch == null) {
            return null;
        }
        fsStatisSalerWatch.setId(null);
        fsStatisSalerWatchMapper.insert(fsStatisSalerWatch);
        return fsStatisSalerWatch;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FsStatisSalerWatch update(FsStatisSalerWatch fsStatisSalerWatch) {
        if (fsStatisSalerWatch == null || fsStatisSalerWatch.getId() == null) {
            return null;
        }
        int affectedRows = fsStatisSalerWatchMapper.update(fsStatisSalerWatch);
        if (affectedRows > 0) {
            return fsStatisSalerWatch;
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean deleteById(Integer id) {
        if (id == null) {
            return false;
        }
        int affectedRows = fsStatisSalerWatchMapper.deleteById(id);
        return affectedRows > 0;
    }

    @Override
    public List<FsStatisSalerWatch> queryList(StatsWatchLogPageListDTO param) {
        if(StringUtils.isNull(param.getStartDate()) && StringUtils.isNull(param.getEndDate())) {
            return Collections.emptyList();
        }
        List<FsStatisSalerWatch> fsStatisSalerWatches = fsStatisSalerWatchMapper.queryList(param);
        for (FsStatisSalerWatch item : fsStatisSalerWatches) {
            if(item.getDeptId() != null) {
                CompanyDept companyDept = companyDeptMapper.selectCompanyDeptById(item.getDeptId());
                if(ObjectUtils.isNotNull(companyDept)) {
                    item.setDeptName(companyDept.getDeptName());
                }
            }
            if(item.getCompanyUserId() != null) {
                String companyUserName = companyUserCacheService.selectCompanyUserNameUserById(item.getCompanyUserId());
                if(StringUtils.isNotEmpty(companyUserName)){
                    item.setCompanyUserName(companyUserName);
                }
            }

            if(item.getPeriodId() != null) {
                String periodName = qwSopLogsMapper.queryPeriodNameById(item.getPeriodId());
                if(StringUtils.isNotEmpty(periodName)) {
                    item.setPeriodName(periodName);
                }
            }


        }
        return fsStatisSalerWatches;
    }

    @Override
    public List<FsStatisSalerWatch> queryPeriodList(StatsWatchLogPageListDTO param) {
        if(StringUtils.isNull(param.getStartDate()) && StringUtils.isNull(param.getEndDate())) {
            return Collections.emptyList();
        }
        List<FsStatisSalerWatch> fsStatisSalerWatches = fsStatisSalerWatchMapper.queryPeriodList(param);
        for (FsStatisSalerWatch item : fsStatisSalerWatches) {
            if(item.getDeptId() != null) {
                CompanyDept companyDept = companyDeptMapper.selectCompanyDeptById(item.getDeptId());
                if(ObjectUtils.isNotNull(companyDept)) {
                    item.setDeptName(companyDept.getDeptName());
                }
            }
            if(item.getCompanyUserId() != null) {
                String companyUserName = companyUserCacheService.selectCompanyUserNameUserById(item.getCompanyUserId());
                if(StringUtils.isNotEmpty(companyUserName)){
                    item.setCompanyUserName(companyUserName);
                }
            }

            if(item.getPeriodId() != null) {
                String periodName = qwSopLogsMapper.queryPeriodNameById(item.getPeriodId());
                if(StringUtils.isNotEmpty(periodName)) {
                    item.setPeriodName(periodName);
                }
            }

        }
        return fsStatisSalerWatches;
    }

    @Override
    public List<FsStatisSalerWatch> queryTodayList(StatsWatchLogPageListDTO param) {
        if(StringUtils.isNull(param.getStartDate()) && StringUtils.isNull(param.getEndDate())) {
            return Collections.emptyList();
        }
        List<FsStatisSalerWatch> fsStatisSalerWatches = fsStatisSalerWatchMapper.queryTodayList(param);
        for (FsStatisSalerWatch item : fsStatisSalerWatches) {
            if(item.getDeptId() != null) {
                CompanyDept companyDept = companyDeptMapper.selectCompanyDeptById(item.getDeptId());
                if(ObjectUtils.isNotNull(companyDept)) {
                    item.setDeptName(companyDept.getDeptName());
                }
            }
            if(item.getCompanyUserId() != null) {
                String companyUserName = companyUserCacheService.selectCompanyUserNameUserById(item.getCompanyUserId());
                if(StringUtils.isNotEmpty(companyUserName)){
                    item.setCompanyUserName(companyUserName);
                }
            }

            if(item.getPeriodId() != null) {
                String periodName = qwSopLogsMapper.queryPeriodNameById(item.getPeriodId());
                if(StringUtils.isNotEmpty(periodName)) {
                    item.setPeriodName(periodName);
                }
            }

        }
        return fsStatisSalerWatches;
    }

    @Override
    public void writeData() {
        // 统计销售看课情况
        // 获取前一天的时间
        List<CompanyUser> companyUserList = this.companyUserMapper.selectAllCompanyUserList();

        List<FsStatisSalerWatch> writeData = new ArrayList<>();

        LocalDate previousDay = LocalDate.now().minusDays(1);
        for (CompanyUser companyUser : companyUserList) {

            if(companyUser.getCompanyId() == null) {
                log.info("销售{} 对应公司id {} 为空！",companyUser.getUserId(),companyUser.getCompanyId());
                continue;
            }
            // 找到销售关联的 企微账号
            List<String> qwUserIdList = qwUserMapper.findQwUserIdListByCompanyUserId(companyUser.getUserId());
            if(CollectionUtils.isEmpty(qwUserIdList)){
                log.info("当前销售 {} 没有关联企微账号！",companyUser.getUserId());
                continue;
            }

            // 确定当前销售对应的sop任务的执行记录
            List<String> periodList = sopUserLogsMapper.selectSopUserLogsByQwUserIds(qwUserIdList);

            if(CollectionUtils.isEmpty(periodList)){
                log.info("当前销售 {} 没有相关的SOP营期！", companyUser.getUserId());
                continue;
            }

            for (String periodId : periodList) {
                // 去sop记录表找对应的SOP发送记录，记录数作为营期人数
                Long periodCount = qwSopLogsMapper.selectQwSopLogsCountByQwUserId(qwUserIdList,periodId,previousDay);
                // 再去course_watch_log找对应的销售观看记录作为已报名数
                Long registerCount = companyUserMapper.queryCompanyUserWatchCount(companyUser.getUserId(),previousDay);
                Long completedCount = companyUserMapper.queryCompanyUserWatchCountCompleted(companyUser.getUserId(),previousDay);
                // 当前销售当天的看课中断数量
                Long interruptCount = companyUserMapper.queryCompanyUserInterruptCount(companyUser.getUserId(),previousDay);

                FsStatisSalerWatch fsStatisSalerWatch = new FsStatisSalerWatch();
                fsStatisSalerWatch.setDeptId(companyUser.getDeptId());
                fsStatisSalerWatch.setCompanyUserId(companyUser.getUserId());
                fsStatisSalerWatch.setTrainCampNum(periodCount);
                fsStatisSalerWatch.setNotRegisteredNum(Math.max(0, periodCount - registerCount));
                fsStatisSalerWatch.setRegisteredNum(registerCount);
                fsStatisSalerWatch.setCompletedNum(completedCount);
                fsStatisSalerWatch.setInterruptNum(interruptCount);

                // 修复比率计算
                float regRate = (periodCount > 0) ? (float) registerCount / periodCount : 0.0f;
                float finishedRate = (registerCount > 0) ? (float) completedCount / registerCount : 0.0f;

                fsStatisSalerWatch.setRegRate(regRate);
                fsStatisSalerWatch.setFinishedRate(finishedRate);
                fsStatisSalerWatch.setDataDate(previousDay);

                fsStatisSalerWatch.setPeriodId(periodId);

                writeData.add(fsStatisSalerWatch);
            }
        }

        if(CollectionUtils.isNotEmpty(writeData)){
            fsStatisSalerWatchMapper.batchSave(writeData);
        }
    }

    @Override
    public void writeDataToday() {
        // 统计销售看课情况
        // 获取前一天的时间
        List<CompanyUser> companyUserList = this.companyUserMapper.selectAllCompanyUserList();

        List<FsStatisSalerWatch> writeData = new ArrayList<>();

        LocalDate nowDay = LocalDate.now();
        for (CompanyUser companyUser : companyUserList) {

            if(companyUser.getCompanyId() == null) {
                log.info("销售{} 对应公司id {} 为空！",companyUser.getUserId(),companyUser.getCompanyId());
                continue;
            }
            // 找到销售关联的 企微账号
            List<String> qwUserIdList = qwUserMapper.findQwUserIdListByCompanyUserId(companyUser.getUserId());
            if(CollectionUtils.isEmpty(qwUserIdList)){
                log.info("当前销售 {} 没有关联企微账号！",companyUser.getUserId());
                continue;
            }

            // 确定当前销售对应的sop任务的执行记录
            List<String> periodList = sopUserLogsMapper.selectSopUserLogsByQwUserIds(qwUserIdList);

            if(CollectionUtils.isEmpty(periodList)){
                log.info("当前销售 {} 没有相关的SOP营期！", companyUser.getUserId());
                continue;
            }

            for (String periodId : periodList) {
                // 去sop记录表找对应的SOP发送记录，记录数作为营期人数
                Long periodCount = qwSopLogsMapper.selectQwSopLogsCountByQwUserId(qwUserIdList,periodId,nowDay);
                // 再去course_watch_log找对应的销售观看记录作为已报名数
                Long registerCount = companyUserMapper.queryCompanyUserWatchCount(companyUser.getUserId(),nowDay);
                Long completedCount = companyUserMapper.queryCompanyUserWatchCountCompleted(companyUser.getUserId(),nowDay);
                // 当前销售当天的看课中断数量
                Long interruptCount = companyUserMapper.queryCompanyUserInterruptCount(companyUser.getUserId(),nowDay);

                FsStatisSalerWatch fsStatisSalerWatch = new FsStatisSalerWatch();
                fsStatisSalerWatch.setDeptId(companyUser.getDeptId());
                fsStatisSalerWatch.setCompanyUserId(companyUser.getUserId());
                fsStatisSalerWatch.setTrainCampNum(periodCount);
                fsStatisSalerWatch.setNotRegisteredNum(Math.max(0, periodCount - registerCount));
                fsStatisSalerWatch.setRegisteredNum(registerCount);
                fsStatisSalerWatch.setCompletedNum(completedCount);
                fsStatisSalerWatch.setInterruptNum(interruptCount);

                // 修复比率计算
                float regRate = (periodCount > 0) ? (float) registerCount / periodCount : 0.0f;
                float finishedRate = (registerCount > 0) ? (float) completedCount / registerCount : 0.0f;

                fsStatisSalerWatch.setRegRate(regRate);
                fsStatisSalerWatch.setFinishedRate(finishedRate);
                fsStatisSalerWatch.setDataDate(nowDay);

                fsStatisSalerWatch.setPeriodId(periodId);

                writeData.add(fsStatisSalerWatch);
            }
        }

        if(CollectionUtils.isNotEmpty(writeData)){
            fsStatisSalerWatchMapper.batchSave(writeData);
        }
    }
}
