package com.fs.course.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.DictUtils;
import com.fs.common.utils.PubFun;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyMapper;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.domain.FsUserCompanyBind;
import com.fs.course.domain.FsUserCourse;
import com.fs.course.mapper.FsCourseWatchLogMapper;
import com.fs.course.mapper.FsUserCompanyBindMapper;
import com.fs.course.mapper.FsUserCourseMapper;
import com.fs.course.service.IFsUserCompanyBindService;
import com.fs.course.service.IUserProjectRepeatMaintainService;
import com.fs.course.support.CourseProjectEquivalence;
import com.fs.course.vo.CourseProgressResultVO;
import com.fs.course.vo.RelatedSalesResultVO;
import com.fs.course.vo.RepeatCourseHistoryVO;
import com.fs.course.vo.RepeatProjectResultVO;
import com.fs.course.vo.UserWatchLogListVo;
import com.fs.his.mapper.FsUserMapper;
import com.fs.qw.domain.QwCompany;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.mapper.QwCompanyMapper;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.param.UserWatchLogParam;
import com.fs.qw.vo.QwOptionsVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

/**
 * 用户客服关联Service业务层处理
 *
 * @author fs
 * @date 2025-07-22
 */
@Slf4j
@Service
@AllArgsConstructor
public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindMapper, FsUserCompanyBind> implements IFsUserCompanyBindService {

    private final CompanyUserMapper companyUserMapper;
    private final IUserProjectRepeatMaintainService userProjectRepeatMaintainService;
    private FsUserMapper fsUserMapper;
    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
    private QwExternalContactMapper qwExternalContactMapper;
    private FsUserCourseMapper fsUserCourseMapper;
    private QwCompanyMapper qwCompanyMapper;
    private QwUserMapper qwUserMapper;
    private CompanyMapper companyMapper;

    /**
     * 查询用户客服关联
     *
     * @param id 用户客服关联主键
     * @return 用户客服关联
     */
    @Override
    public FsUserCompanyBind selectFsUserCompanyBindById(Long id) {
        return baseMapper.selectFsUserCompanyBindById(id);
    }

    /**
     * 查询用户客服关联列表
     *
     * @param fsUserCompanyBind 用户客服关联
     * @return 用户客服关联
     */
    @Override
    public List<FsUserCompanyBind> selectFsUserCompanyBindList(FsUserCompanyBind fsUserCompanyBind) {
        return baseMapper.selectFsUserCompanyBindList(fsUserCompanyBind);
    }

    /**
     * 新增用户客服关联
     *
     * @param fsUserCompanyBind 用户客服关联
     * @return 结果
     */
    @Override
    public int insertFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind) {
        fsUserCompanyBind.setCreateTime(DateUtils.getNowDate());
        return baseMapper.insertFsUserCompanyBind(fsUserCompanyBind);
    }

    /**
     * 修改用户客服关联
     *
     * @param fsUserCompanyBind 用户客服关联
     * @return 结果
     */
    @Override
    public int updateFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind) {
        fsUserCompanyBind.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateFsUserCompanyBind(fsUserCompanyBind);
    }

    /**
     * 批量删除用户客服关联
     *
     * @param ids 需要删除的用户客服关联主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCompanyBindByIds(Long[] ids) {
        return baseMapper.deleteFsUserCompanyBindByIds(ids);
    }

    /**
     * 删除用户客服关联信息
     *
     * @param id 用户客服关联主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCompanyBindById(Long id) {
        return baseMapper.deleteFsUserCompanyBindById(id);
    }

    @Override
    public boolean bindFsUser(Long fsUserId, Long externalUserId, Long watchLogId) {
        try {
            QwExternalContact qwExternalContact = qwExternalContactMapper.selectById(externalUserId);
            FsCourseWatchLog watchLog = fsCourseWatchLogMapper.selectById(watchLogId);
            FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(watchLog.getCourseId());
            Company company = companyMapper.selectCompanyById(qwExternalContact.getCompanyId());
            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(qwExternalContact.getCorpId());
            // 员工ID
            Long companyUserId = qwExternalContact.getCompanyUserId();
            // 公司ID
            Long companyId = qwExternalContact.getCompanyId();
            // 企微用户ID
            Long qwUserId = qwExternalContact.getQwUserId();
            // 项目
            Long project = course.getProject() == null ? 0 : course.getProject();
            // 企微主体ID
            Long qwCompanyId = qwCompany.getId();
            // 课程ID
            Long courseId = watchLog.getCourseId();
            // 视频ID
            Long videoId = watchLog.getVideoId();
            // 看课记录ID
            Long logId = watchLog.getLogId();
            // 看课状态
            Integer logType = watchLog.getLogType();
            if (company.getRepeat() == 1 && project != 0) {
                List<FsUserCompanyBind> list = baseMapper.selectList(new QueryWrapper<FsUserCompanyBind>().eq("fs_user_id", fsUserId).eq("project_id", project).last(" GROUP BY qw_user_id"));
                if (!list.isEmpty() && list.stream().noneMatch(e -> e.getQwUserId().equals(qwUserId))) {
                    log.error("当前客户：{}已经有所属项目{}， 企微ID：{}， 当前企微ID：{}", fsUserId, project, PubFun.listToNewList(list, FsUserCompanyBind::getQwUserId), qwUserId);
                    return false;
                }
            }
            if (qwExternalContact.getUserRepeat() == 0 && project != 0
                    && userProjectRepeatMaintainService.isRepeatByProject(fsUserId, project)) {
                qwExternalContact.setUserRepeat(1);
                qwExternalContactMapper.updateById(qwExternalContact);
            }
            // 当前登录账号名称
            FsUserCompanyBind one = baseMapper.selectOne(new QueryWrapper<FsUserCompanyBind>()
                    .eq("fs_user_id", fsUserId)
                    .eq("project_id", project)
                    .eq("course_id", courseId)
                    .eq("qw_user_id", qwUserId)
                    .eq("company_user_id", companyUserId)
                    .eq("video_id", videoId));
            if (one == null) {
                FsUserCompanyBind bind = new FsUserCompanyBind();
                bind.setFsUserId(fsUserId);
                bind.setCompanyUserId(companyUserId);
                bind.setCompanyId(companyId);
                bind.setQwUserId(qwUserId);
                bind.setQwExternalContactId(externalUserId);
                bind.setProjectId(project);
                bind.setQwCompanyId(qwCompanyId);
                bind.setCourseId(courseId);
                bind.setVideoId(videoId);
                bind.setWatchLogId(logId);
                bind.setLogType(logType);
                bind.setCreateTime(new Date());
                bind.setUpdateTime(new Date());
                if (bind.getLogType() == 2) {
                    bind.setFinishTime(LocalDateTime.now());
                }
                try {
                    save(bind);
                    userProjectRepeatMaintainService.maintain(fsUserId, project, qwUserId, companyId);
                } catch (Exception e) {
                    log.error("添加重粉失败", e);
                }
            }
            return true;
        }catch (Exception e){
            log.error("绑定关系错误", e);
            return false;
        }
    }

    @Override
    public void finish(Long fsUserId, Long qwUserId, Long companyUserId, FsCourseWatchLog watchLog) {
        FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(watchLog.getCourseId());
        FsUserCompanyBind one = baseMapper.selectOne(new QueryWrapper<FsUserCompanyBind>()
                .eq("fs_user_id", fsUserId)
                .eq("project_id", course.getProject())
                .eq("course_id", watchLog.getCourseId())
                .eq("qw_user_id", qwUserId)
                .eq("company_user_id", companyUserId)
                .eq("video_id", watchLog.getVideoId()));
        if(one == null){
            CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(companyUser.getCorpId());
            one = new FsUserCompanyBind();
            one.setFsUserId(fsUserId);
            one.setCompanyUserId(companyUserId);
            one.setCompanyId(companyUser.getCompanyId());
            one.setQwUserId(qwUserId);
            one.setQwExternalContactId(watchLog.getQwExternalContactId());
            one.setProjectId(course.getProject());
            one.setQwCompanyId(qwCompany != null ? qwCompany.getId() : null);
            one.setCourseId(watchLog.getCourseId());
            one.setVideoId(watchLog.getVideoId());
            one.setWatchLogId(watchLog.getLogId());
            one.setLogType(2);
            one.setFinishTime(LocalDateTime.now());
            one.setCreateTime(new Date());
            one.setUpdateTime(new Date());
            try {
                save(one);
                userProjectRepeatMaintainService.maintain(fsUserId, course.getProject(), qwUserId, one.getCompanyId());
            } catch (Exception e) {
                log.error("添加重粉失败", e);
            }
        }else{
            one.setFinishTime(LocalDateTime.now());
            one.setLogType(2);
            updateById(one);
        }
    }

    @Override
    public List<UserWatchLogListVo> getWatchLogList(UserWatchLogParam param) {
        if(param.getExternalUserId() == null &&  param.getFsUserId() == null){
            return Collections.emptyList();
        }
        if (param.getProjectId() != null && param.getProjectId() != 0) {
            param.setEquivalentProjectIds(
                    CourseProjectEquivalence.equivalentProjectIds(param.getProjectId().longValue()));
        }
        List<UserWatchLogListVo> list = baseMapper.getWatchLogList(param);
        // 权限判断：如果传了companyId，对无权限的主体脱敏
        if (param.getCompanyId() != null && list != null) {
            List<String> permittedCorpIds = getPermittedCorpIds(param.getCompanyId());
            for (UserWatchLogListVo vo : list) {
                boolean hasPermission = vo.getCorpId() == null || permittedCorpIds.contains(vo.getCorpId());
                vo.setHasPermission(hasPermission);
                if (!hasPermission) {
                    vo.setQwUserName("***");
                    vo.setCorpName("***");
                }
            }
        }
        return list;
    }

    @Override
    public RepeatCourseHistoryVO getRepeatCourseHistory(Long fsUserId, Long companyId) {
        RepeatCourseHistoryVO vo = new RepeatCourseHistoryVO();

        // 查询当前用户公司有权限的企微主体corpId列表
        List<String> permittedCorpIds = getPermittedCorpIds(companyId);

        // 1. 查询客户基本信息
        QwExternalContact contact = qwExternalContactMapper.selectOne(
                new QueryWrapper<QwExternalContact>()
                        .eq("fs_user_id", fsUserId)
                        .eq("status", 0)
                        .last("LIMIT 1")
        );
        if (contact != null) {
            vo.setName(contact.getName());
            vo.setAvatar(contact.getAvatar());
            vo.setRemark(contact.getRemark());
        }
        vo.setUserRepeat(userProjectRepeatMaintainService.isRepeatInAnyProject(fsUserId) ? 1 : 0);
        vo.setProjectList(buildUserProjectList(fsUserId));

        // 2. 查询关联销售（单条SQL + GROUP BY 优化）
        List<RelatedSalesResultVO> salesResults = baseMapper.getRelatedSalesByFsUserId(fsUserId);
        List<RepeatCourseHistoryVO.RelatedSalesVO> salesList = new ArrayList<>();
        for (RelatedSalesResultVO r : salesResults) {
            RepeatCourseHistoryVO.RelatedSalesVO s = new RepeatCourseHistoryVO.RelatedSalesVO();
            boolean hasPermission = hasCorpPermission(companyId, permittedCorpIds, r.getCorpId());
            s.setHasPermission(hasPermission);
            if (hasPermission) {
                s.setQwUserName(r.getQwUserName());
                s.setCorpName(r.getCorpName());
            } else {
                s.setQwUserName("***");
                s.setCorpName("***");
            }
            s.setAddTime(r.getAddTime());
            s.setStatus(r.getStatus());
            salesList.add(s);
        }
        vo.setSalesList(salesList);

        // 3. 查询课程学习进度（单条SQL + 子查询优化）
        List<CourseProgressResultVO> courseResults = baseMapper.getCourseProgressByFsUserId(fsUserId);
        List<RepeatCourseHistoryVO.CourseProgressVO> courseList = new ArrayList<>();
        for (CourseProgressResultVO c : courseResults) {
            RepeatCourseHistoryVO.CourseProgressVO cp = new RepeatCourseHistoryVO.CourseProgressVO();
            cp.setCourseId(c.getCourseId());
            cp.setCourseName(c.getCourseName());
            cp.setProjectId(c.getProjectId());
            cp.setTotalCount(c.getTotalCount() != null ? c.getTotalCount() : 0);
            cp.setWatchedCount(c.getWatchedCount() != null ? c.getWatchedCount() : 0);
            // 计算百分比
            int total = cp.getTotalCount();
            int watched = cp.getWatchedCount();
            cp.setPercentage(total > 0 ? (watched * 100 / total) : 0);
            cp.setLatestSection(c.getLatestSection());
            cp.setLatestTime(c.getLatestTime());
            cp.setFinished(total > 0 && watched >= total);
            boolean hasPermission = hasCorpPermission(companyId, permittedCorpIds, c.getCorpId());
            cp.setHasPermission(hasPermission);
            if (hasPermission) {
                cp.setQwUserName(c.getQwUserName());
                cp.setCorpName(c.getCorpName());
            } else {
                cp.setQwUserName("***");
                cp.setCorpName("***");
            }
            courseList.add(cp);
        }
        vo.setCourseList(courseList);

        return vo;
    }

    /**
     * 根据运营公司ID查询有权限的企微主体corpId列表
     */
    private List<String> getPermittedCorpIds(Long companyId) {
        List<QwOptionsVO> companyList = qwUserMapper.selectQwCompanyListOptionsVOByCompanyId(companyId);
        List<String> corpIds = new ArrayList<>();
        if (companyList != null) {
            for (QwOptionsVO vo : companyList) {
                if (vo.getDictValue() != null) {
                    corpIds.add(vo.getDictValue());
                }
            }
        }
        return corpIds;
    }

    private boolean hasCorpPermission(Long companyId, List<String> permittedCorpIds, String corpId) {
        if (companyId == null) {
            return true;
        }
        return corpId == null || permittedCorpIds.contains(corpId);
    }

    /**
     * 构建客户企微发课看过的项目列表：等价项目（如百膳食养/安康食养）分项展示，重粉项目标记 isRepeat=1。
     */
    private List<RepeatCourseHistoryVO.RepeatProjectVO> buildUserProjectList(Long fsUserId) {
        List<RepeatProjectResultVO> watched = baseMapper.getUserWatchedProjectsByFsUserId(fsUserId);
        Map<Long, String> nameMap = new HashMap<>();
        TreeSet<Long> projectIds = new TreeSet<>();
        if (watched != null) {
            for (RepeatProjectResultVO item : watched) {
                if (item.getProjectId() == null) {
                    continue;
                }
                projectIds.add(item.getProjectId());
                if (item.getProjectName() != null) {
                    nameMap.put(item.getProjectId(), item.getProjectName());
                }
            }
        }
        // 等价项目组 1/28：只要看过其中任一，两个项目名都展示
        if (projectIds.contains(1L) || projectIds.contains(28L)) {
            projectIds.add(1L);
            projectIds.add(28L);
        }
        List<RepeatCourseHistoryVO.RepeatProjectVO> list = new ArrayList<>();
        for (Long projectId : projectIds) {
            RepeatCourseHistoryVO.RepeatProjectVO vo = new RepeatCourseHistoryVO.RepeatProjectVO();
            vo.setProjectId(projectId);
            String projectName = nameMap.get(projectId);
            if (projectName == null) {
                projectName = DictUtils.getDictLabel("sys_course_project", String.valueOf(projectId));
            }
            vo.setProjectName(projectName);
            vo.setIsRepeat(userProjectRepeatMaintainService.isRepeatByProject(fsUserId, projectId) ? 1 : 0);
            list.add(vo);
        }
        return list;
    }
}
