package com.yizhi.application.project.controller;

import java.util.*;
import java.util.stream.Collectors;

import com.yizhi.site.application.feign.api.EventTrackApiClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.plugins.Page;
import com.yizhi.application.project.controller.util.ProjectWorkUtil;
import com.yizhi.core.application.cache.RedisCache;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.course.application.feign.CoursePcClient;
import com.yizhi.enroll.application.feign.EnrollFeignClient;
import com.yizhi.enroll.application.vo.GetEnrollVO;
import com.yizhi.live.application.feign.LiveActivityClient;
import com.yizhi.site.application.enums.FunctionTypeCode;
import com.yizhi.site.application.feign.api.FunctionDisplayConfigApiClients;
import com.yizhi.site.application.vo.domain.FunctionDisplayConfigVo;
import com.yizhi.training.application.constant.CertificateGrantStatus;
import com.yizhi.training.application.feign.TpPlanActivityClient;
import com.yizhi.training.application.feign.TrainingProjectClient;
import com.yizhi.training.application.model.BaseModel;
import com.yizhi.training.application.vo.api.HotEnrollListVo;
import com.yizhi.training.application.vo.api.HotEnrollParamVo;
import com.yizhi.training.application.vo.api.IdVo;
import com.yizhi.training.application.vo.api.TrainingProjectDetailVo;
import com.yizhi.training.application.vo.api.TrainingProjectIntroductionEnrollVo;
import com.yizhi.training.application.vo.api.TrainingProjectIntroductionVo;
import com.yizhi.training.application.vo.api.TrainingProjectListVo;
import com.yizhi.training.application.vo.api.TrainingProjectMyParamVo;
import com.yizhi.training.application.vo.api.TrainingProjectParamVo;
import com.yizhi.training.application.vo.domain.TpAuthorizationRangeVo;
import com.yizhi.training.application.vo.domain.TrainingActivityVO;
import com.yizhi.training.application.vo.domain.TrainingProjectVo;
import com.yizhi.util.application.constant.ReturnCode;
import com.yizhi.util.application.domain.Response;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author: shengchenglong
 * @Date: 2018/3/27 20:54
 */
@Api(tags = "培训项目接口")
@RestController
@RequestMapping("/api/trainingProject")
public class TrainingProjectController {

    private static final Logger LOGGER = LoggerFactory.getLogger(TrainingProjectController.class);

    @Autowired
    private TrainingProjectClient trainingProjectClient;
    @Autowired
    private EnrollFeignClient enrollFeignClient;
    @Autowired
    LiveActivityClient liveActivityClient;
    @Autowired
    private TpPlanActivityClient tpPlanActivityClient;
    @Autowired
    private FunctionDisplayConfigApiClients configApiClients;
    @Autowired
    private CoursePcClient coursePcClient;
    @Autowired
    RedisCache redisCache;
    @Autowired
    private ProjectWorkUtil workUtil;

    @Autowired
    private EventTrackApiClients eventTrackApiClients;



    @PostMapping("/page/list")
    @ApiOperation(value = "培训项目首页列表", response = TrainingProjectListVo.class)
    public Response<Page<TrainingProjectListVo>> pageList(
            @ApiParam(value = "学员端培训项目列表查询参数vo", required = true) @RequestBody TrainingProjectParamVo vo) {

        try {
            RequestContext context = ContextHolder.get();

            BaseModel<TrainingProjectParamVo> model = new BaseModel<>();
            model.setContext(context);
            model.setDate(new Date());
            model.setObj(vo);
            Page<TrainingProjectListVo> resultPage = trainingProjectClient.apiPageList(model);

            List<TrainingProjectListVo> listVos = resultPage.getRecords();
            List<FunctionDisplayConfigVo> dataFunction = configApiClients.getAllBySiteId();

            Boolean trainingDurationShow = false;
            if (!CollectionUtils.isEmpty(dataFunction)) {
                for (FunctionDisplayConfigVo a : dataFunction) {
                    if (FunctionTypeCode.TRAINING.getCode().equals(a.getFunctionType())) {
                        trainingDurationShow = a.getShowDisplay();
                    }
                }
            }
            
            /*//2024-11-28注释，不需要调用课程服务
            List<Long> trProectIds = new ArrayList<>();
            if (!CollectionUtils.isEmpty(listVos)) {
                for (TrainingProjectListVo tr : listVos) {
                    List<Long> listCourseIds = tr.getListCourseIds();
                    tr.setPeriod(0f);
                    tr.setTrainingDurationShow(trainingDurationShow);
                    if (!CollectionUtils.isEmpty(listCourseIds)) {
                        Float allMaterialTime = 0f;
                        Map<Long, Float> map = coursePcClient.getStudyHourByCourseIds(listCourseIds);
                        if (null != map) {
                            for (Long courseId : listCourseIds) {
                                Float materialTime = map.get(courseId);
                                allMaterialTime = (null == materialTime ? 0 : materialTime) + allMaterialTime;
                                tr.setPeriod(allMaterialTime);
                            }
                        }
                    }
                }
            }*/

            return Response.ok(resultPage);
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }

    /**
     * 火热报名列表
     *
     * @param vo
     * @return
     */
    @ApiOperation(value = "火热报名列表", response = HotEnrollListVo.class)
    @PostMapping("/hot/page/list")
    public Response<Page<HotEnrollListVo>> apiHotPageList(
            @ApiParam(value = "火热报名列表参数", required = true) @RequestBody HotEnrollParamVo vo) {
        try {
            BaseModel<HotEnrollParamVo> model = new BaseModel<>();
            model.setContext(ContextHolder.get());
            model.setDate(new Date());
            model.setObj(vo);
            Page<HotEnrollListVo> resultPage = trainingProjectClient.apiHotPageListV2(model);
            List<HotEnrollListVo> listVos = resultPage.getRecords();
            List<FunctionDisplayConfigVo> dataFunction = configApiClients.getAllBySiteId();
            Boolean trainingDurationShow = false;
            if (!CollectionUtils.isEmpty(dataFunction)) {
                for (FunctionDisplayConfigVo a : dataFunction) {
                    if (FunctionTypeCode.TRAINING.getCode().equals(a.getFunctionType())) {
                        trainingDurationShow = a.getShowDisplay();

                    }
                }
            }
            if (!CollectionUtils.isEmpty(listVos)) {
                for (HotEnrollListVo tr : listVos) {
                    List<Long> listCourseIds = tr.getListCourseIds();
                    tr.setPeriod(0f);
                    tr.setTrainingDurationShow(trainingDurationShow);
                    if (!CollectionUtils.isEmpty(listCourseIds)) {
                        Float allMaterialTime = 0f;

                        Map<Long, Float> map = coursePcClient.getStudyHourByCourseIds(listCourseIds);
                        if (null != map) {
                            for (Long courseId : listCourseIds) {
                                Float materialTime = map.get(courseId);
                                allMaterialTime = (null == materialTime ? 0 : materialTime) + allMaterialTime;
                                tr.setPeriod(allMaterialTime);
                            }
                        }
                    }
                }
            }
            return Response.ok(resultPage);
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }

    @PostMapping("/my/page/list")
    @ApiOperation(value = "我的培训", response = TrainingProjectListVo.class)
    public Response<Page<TrainingProjectListVo>> myPageList(
            @ApiParam(value = "学员端我的培训项目列表查询参数vo", required = true) @RequestBody TrainingProjectMyParamVo vo
    ) {
        try {
            RequestContext context = ContextHolder.get();
            BaseModel<TrainingProjectMyParamVo> model = new BaseModel<>();
            model.setContext(context);
            model.setDate(new Date());
            model.setObj(vo);
            Page<TrainingProjectListVo> voPage = trainingProjectClient.apiMyPageList(model);
            return Response.ok(voPage);
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }

    }

    //2018.09.13添加扫码查看接口
    @PostMapping("/one/detail/view/scan")
    @ApiOperation(value = "培训详情扫码查看", response = TrainingProjectDetailVo.class)
    public Response<TrainingProjectDetailVo> getTpDetailScan(@ApiParam(value = "培训项目id，格式：{\"id\": 123}", required = true) @RequestBody IdVo idVo) {
        RequestContext res = ContextHolder.get();
        List<Long> relationIds = res.getRelationIds();
        Long siteId = res.getSiteId();
        Long accountId = res.getAccountId();
        Long projectId = idVo.getId();
        TrainingProjectVo project = trainingProjectClient.getOne(projectId);
        boolean isPass = false;
        if (project.getVisibleRange() != null && project.getVisibleRange() == 1) {
            if (project.getSiteId() != null && siteId != null && project.getSiteId().equals(siteId)) {
                isPass = true;
            }
        } else if (project.getVisibleRange() != null && project.getVisibleRange() == 0) {
            List<TpAuthorizationRangeVo> authorizationRanges = trainingProjectClient.VisibleRange(projectId);
            List<Long> rangeIds = authorizationRanges.stream().map(TpAuthorizationRangeVo::getRelationId).collect(Collectors.toList());
            if (rangeIds.contains(accountId)) {
                isPass = true;
            } else {
                for (Long rangeId : rangeIds) {
                    if (relationIds.contains(rangeId)) {
                        isPass = true;
                        break;
                    }
                }
            }
        }
        if (isPass) {
            return getTpDetail(idVo);
        } else {
            return Response.fail("4001", "无权访问");
        }

    }

    /**
     * 移动端获取项目详情
     * 前端根据如下字段展示
     * needEnroll, needAudit,EnablePay, hasEnrolled, audited
     * 移动端是这个四个字段，需要报名，需要审核，是否付费, 已报名，已审核
     */
    @PostMapping("/one/detail/view")
    @ApiOperation(value = "培训详情", response = TrainingProjectDetailVo.class)
    public Response<TrainingProjectDetailVo> getTpDetail(
            @ApiParam(value = "培训项目id，格式：{\"id\": 123}", required = true) @RequestBody IdVo idVo
    ) {
        try {

            BaseModel<Long> model = new BaseModel<>();
            model.setObj(idVo.getId());
            model.setDate(new Date());
            RequestContext context = ContextHolder.get();
            model.setContext(context);
            Long accountId = context.getAccountId();
            Long siteId = context.getSiteId();

            TrainingProjectDetailVo vo = trainingProjectClient.getTpDetail(model);
            // 如果查询到培训项目
            if (null != vo) {
                TrainingProjectIntroductionVo introductionVo = vo.getIntroductionVo();
                // 如果需要报名
                if (vo.getIntroductionVo().getNeedEnroll()) {
                    try {
                        GetEnrollVO enroll = enrollFeignClient.getEnrollByProjectId(idVo.getId(), ContextHolder.get().getAccountId());
                        LOGGER.info("需要报名培训项目：{}，查询到报名：{}", vo.getIntroductionVo().getName(), enroll.toString());
                        if (enroll != null) {
                            TrainingProjectIntroductionEnrollVo enrollVo = new TrainingProjectIntroductionEnrollVo();
                            enrollVo.setId(enroll.getId());
                            enrollVo.setStartTime(enroll.getStartTime());
                            enrollVo.setEndTime(enroll.getEndTime());
                            enrollVo.setLimit(enroll.getLimit());
                            enrollVo.setNotice(enroll.getNotice());
                            vo.getIntroductionVo().setEnroll(enrollVo);

                            vo.getIntroductionVo().setEnrollLimit(enroll.getLimit());
                            vo.getIntroductionVo().setHasEnrolled(enroll.getHasEnrolled());
                            vo.getIntroductionVo().setAuditStatus(enroll.getAuditStatus());
                            Integer auditStatus = enroll.getAuditStatus();
                            vo.getIntroductionVo().setAudited(auditStatus == 2 || auditStatus == 3);
                            vo.getIntroductionVo().setNeedAudit(enroll.getNeedAudit());
                            vo.getIntroductionVo().setHasEnrolledNum(enroll.getHasEnrolledNum());
                            //是否需要付费
                            vo.getIntroductionVo().setEnablePay(enroll.getEnablePay());
                            vo.getIntroductionVo().setActualPrice(enroll.getActualPrice());
                            vo.getIntroductionVo().setOriginalPrice(enroll.getOriginalPrice());
                        }
                    } catch (Exception e) {
                        LOGGER.error("需要报名培训项目：{}，没有查询到报名", vo.getIntroductionVo().getName());
                    }
                }

                // 查询直播频道号需要
                /*List<TrainingProjectContentPlanVo> dataList = vo.getContentVo().getPlans();
                Integer minPoint = 0;
                Integer maxPoint = 0;

                //组装其直播频道 ，顺便计算积分
                //暂时不计算活动积分
                Boolean enabled = false;
                Map map = workUtil.buildMap(dataList, introductionVo, enabled);
                if (map != null) {
                    dataList = (List<TrainingProjectContentPlanVo>) map.get("dataList");
                    if (enabled) {
                        minPoint = workUtil.returnNumber(map.get("minPoint"));
                        maxPoint = workUtil.returnNumber(map.get("maxPoint"));
                    }
                }
                introductionVo.setEnablePoint(introductionVo.getPoint() <= 0 ? false : true);
                introductionVo.setMaxPoint(maxPoint);
                introductionVo.setMinPoint(minPoint);*/
            }
            // 查询直播的观看权限类型
            /*List<TrainingProjectContentPlanVo> dataAll = vo.getContentVo().getPlans();
            if(! CollectionUtils.isEmpty(dataAll)){
                for(TrainingProjectContentPlanVo item : dataAll){
                    List<TrainingProjectContentActivityVo> inData = item.getActivities();
                    List<Long> filterData = inData.parallelStream().filter(filterItem ->
                            Integer.valueOf(3).equals(filterItem.getType())).map(dataItem-> dataItem.getRelationId()).collect(Collectors.toList());
                    if(filterData != null){
                        Page<LiveActivityVO> liveData = liveActivityClient.LiveActivityByIds(filterData,0,filterData.size());
                        Map<Long,Integer> dataMap = liveData.getRecords().stream().
                                collect(Collectors.toMap(key->key.getId(),val->val.getViewType()));
                        for(TrainingProjectContentActivityVo itemTmp :  inData){
                            if(Integer.valueOf(3).equals(itemTmp.getType()) && dataMap.containsKey(itemTmp.getRelationId())){
                                itemTmp.setViewType(dataMap.get(itemTmp.getRelationId()));
                            }
                        }
                    }
                }
            }*/
            return Response.ok(vo);

        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }





    @PostMapping("/one/detail/progress/view")
    @ApiOperation(value = "培训详情，带学习统计", response = TrainingProjectDetailVo.class)
    public Response<TrainingProjectDetailVo> getTpDetailWithProgress(
            @ApiParam(value = "培训项目id，格式：{\"id\": 123}", required = true) @RequestBody IdVo idVo
    ) {
        try {
            BaseModel<Long> model = new BaseModel<>();
            model.setObj(idVo.getId());
            model.setDate(new Date());
            model.setContext(ContextHolder.get());

            TrainingProjectDetailVo vo = trainingProjectClient.getTpDetailWithProgress(model);
            // 如果查询到培训项目
            if (null != vo) {
                TrainingProjectIntroductionVo introductionVo = vo.getIntroductionVo();
                // 如果需要报名
                if (vo.getIntroductionVo().getNeedEnroll()) {
                    try {
                        GetEnrollVO enroll = enrollFeignClient.getEnrollByProjectId(idVo.getId(), ContextHolder.get().getAccountId());
                        LOGGER.info("需要报名培训项目：{}，查询到报名：{}", vo.getIntroductionVo().getName(), enroll.toString());
                        if (enroll != null) {
                            TrainingProjectIntroductionEnrollVo enrollVo = new TrainingProjectIntroductionEnrollVo();
                            enrollVo.setId(enroll.getId());
                            enrollVo.setStartTime(enroll.getStartTime());
                            enrollVo.setEndTime(enroll.getEndTime());
                            enrollVo.setLimit(enroll.getLimit());
                            enrollVo.setNotice(enroll.getNotice());
                            vo.getIntroductionVo().setEnroll(enrollVo);

                            vo.getIntroductionVo().setEnrollLimit(enroll.getLimit());
                            vo.getIntroductionVo().setHasEnrolled(enroll.getHasEnrolled());
                            vo.getIntroductionVo().setAuditStatus(enroll.getAuditStatus());
                            vo.getIntroductionVo().setAudited(enroll.getAuditStatus() == 2);
                            vo.getIntroductionVo().setNeedAudit(enroll.getNeedAudit());
                            vo.getIntroductionVo().setHasEnrolledNum(enroll.getHasEnrolledNum());
                        }
                    } catch (Exception e) {
                        LOGGER.error("需要报名培训项目：{}，没有查询到报名", vo.getIntroductionVo().getName());
                    }
                }
                // 查询直播频道号需要
                /*List<TrainingProjectContentPlanVo> dataList = vo.getContentVo().getPlans();
                Integer minPoint = 0;
                Integer maxPoint = 0;

                //组装其直播频道 ，顺便计算积分
                //暂时不计算活动积分
                Boolean enabled = false;
                Map map = workUtil.buildMap(dataList, introductionVo, enabled);
                if (map != null) {
                    dataList = (List<TrainingProjectContentPlanVo>) map.get("dataList");
                    if (enabled) {
                        minPoint = workUtil.returnNumber(map.get("minPoint"));
                        maxPoint = workUtil.returnNumber(map.get("maxPoint"));
                    }
                }
                introductionVo.setEnablePoint(introductionVo.getPoint() <= 0 ? false : true);
                introductionVo.setMaxPoint(maxPoint);
                introductionVo.setMinPoint(minPoint);*/
            }

            // 查询直播的观看权限类型
            /*List<TrainingProjectContentPlanVo> dataAll = vo.getContentVo().getPlans();
            if(! CollectionUtils.isEmpty(dataAll)){
                for(TrainingProjectContentPlanVo item : dataAll){
                    List<TrainingProjectContentActivityVo> inData = item.getActivities();
                    List<Long> filterData = inData.parallelStream().filter(filterItem ->
                            Integer.valueOf(3).equals(filterItem.getType())).map(dataItem-> dataItem.getRelationId()).collect(Collectors.toList());
                    if(filterData != null){
                        Page<LiveActivityVO> liveData = liveActivityClient.LiveActivityByIds(filterData,0,filterData.size());
                        Map<Long,Integer> dataMap = liveData.getRecords().stream().
                                collect(Collectors.toMap(key->key.getId(),val->val.getViewType()));
                        for(TrainingProjectContentActivityVo itemTmp :  inData){
                            if(Integer.valueOf(3).equals(itemTmp.getType()) && dataMap.containsKey(itemTmp.getRelationId())){
                                itemTmp.setViewType(dataMap.get(itemTmp.getRelationId()));
                            }
                        }
                    }
                }
            }*/

            return Response.ok(vo);
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }

    @PostMapping("/tpPlanActivity/view/record/add")
    @ApiOperation(value = "培训活动浏览记录")
    public Response addViewRecord(
            @ApiParam(value = "培训项目活动id，格式：{\"id\": 123}", required = true) @RequestBody IdVo idVo) {
        try {
            if (null == idVo.getId()) {
                return Response.fail("4001", "活动id必传");
            }
            BaseModel<Long> baseModel = new BaseModel<>();
            baseModel.setDate(new Date());
            baseModel.setContext(ContextHolder.get());
            baseModel.setObj(idVo.getId());
            return Response.ok(tpPlanActivityClient.addViewRecord(baseModel));
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }

    @PostMapping("/certificate/grant")
    @ApiOperation(value = "点击发放证书")
    public Response<String> grantCertificate(
            @ApiParam("参数：{\"certificateId\" : \"111\", \"planId\": \"111\"}")@RequestBody Map<String, Long> param) {
        try {
            Long certificateId = param.get("certificateId");
            Long planId = param.get("planId");

            if (null == certificateId || certificateId.equals(0L) || null == planId || planId.equals(0L)) {
                return Response.fail("4001", "参数传递有误");
            }
            RequestContext context = ContextHolder.get();

            param.put("companyId", context.getCompanyId());
            param.put("siteId", context.getSiteId());
            param.put("accountId", context.getAccountId());

            CertificateGrantStatus status = tpPlanActivityClient.certificateGrant(param);

            return Response.ok(status.getValue());
        } catch (Exception e) {
            LOGGER.error("", e);
            return Response.fail(ReturnCode.SERVICE_UNAVAILABLE.getCode(),ReturnCode.SERVICE_UNAVAILABLE.getMsg());
        }
    }
    
    /**
     * 获取有活动的日期
     * @param bizType 业务类型:1活动服务;2培训测试
     * @param startDate
     * @param endDate
     * @return
     */
    @GetMapping("/getTrainingActivity")
    public Response<TrainingActivityVO> getTrainingActivity(HttpServletRequest request, @RequestParam("bizType") Integer bizType,
                                                            @RequestParam(name = "startDate", required = false) String startDate, @RequestParam(name = "endDate", required = false) String endDate) {
    	TrainingActivityVO result = trainingProjectClient.getTrainingActivity(bizType, startDate, endDate);

        RequestContext context = ContextHolder.get();
        // 添加活动埋点
        if(request.getHeader("Cookie")!=null&&Objects.equals(redisCache.get(request.getHeader("Cookie").replace("JSESSIONID=","")),"2")){
            eventTrackApiClients.addEvent("event_training_activity",context.getAccountId());
        }
    	return Response.ok(result);
    }
}
