package com.softwarebr.nunu.service.train.impl;

import com.brframework.common.utils.ConvertObjectUtil;
import com.brframework.commondb.core.AbstractEntityService;
import com.brframework.commondb.core.CommonRepository;
import com.brframework.commondb.core.ExQuery;
import com.brframework.commonmq.annotation.MQConfig;
import com.brframework.commonmq.core.MQClient;
import com.brframework.commonweb.exception.HandleException;
import com.brframework.commonweb.json.PageParam;
import com.google.common.collect.Maps;
import com.softwarebr.nunu.dao.train.ActivityDao;
import com.softwarebr.nunu.dto.ser.PlatformParamDTO;
import com.softwarebr.nunu.dto.train.ActivityParamDTO;
import com.softwarebr.nunu.entity.ser.Platform;
import com.softwarebr.nunu.entity.train.Activity;
import com.softwarebr.nunu.entity.train.QActivity;
import com.softwarebr.nunu.entity.user.Member;
import com.softwarebr.nunu.entity.user.Message;
import com.softwarebr.nunu.globals.MQTopics;
import com.softwarebr.nunu.globals.SystemConst;
import com.softwarebr.nunu.json.admin.train.ActivityQueryParam;
import com.softwarebr.nunu.service.train.ActivityService;
import com.softwarebr.nunu.service.user.MessageService;
import com.softwarebr.nunu.util.AmountConversionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

import static com.brframework.commondb.core.ControllerPageHandle.convertTo;

/**
 * @author lilin
 * @date 2020-02-26 11:02:46
 */

@Slf4j
@Service
@MQConfig
public class ActivityServiceImpl extends AbstractEntityService<Activity, Long, Object> implements ActivityService {

    @Autowired
    private ActivityDao activityDao;

    @Autowired
    private MQClient mqClient;

    @Autowired
    private MessageService messageService;

    @Override
    public CommonRepository<Long, Activity> getRepository() {
        return activityDao;
    }

    /**
     * 活动状态处理Api
     *
     * @param activity
     * @return
     */
    @Override
    public Map<Integer, String> activityStatusApi(Activity activity) {
        Map<Integer, String> status = Maps.newHashMap();
        if (activity.getSignStartDate().compareTo(LocalDateTime.now()) > 0) {
            status.put(1, "活动预热中");
            return status;
        } else if (activity.getSignStartDate().compareTo(LocalDateTime.now()) <= 0
                && activity.getSignEndDate().compareTo(LocalDateTime.now()) >= 0) {
            if (activity.getEnrolment() >= activity.getCapacity()) {
                status.put(4, "已爆满");
                return status;
            }
            status.put(2, "报名中");
            return status;
        } else if (activity.getSignEndDate().compareTo(LocalDateTime.now()) <= 0
                && activity.getStartDate().compareTo(LocalDateTime.now()) > 0) {
            status.put(3, "报名时间截止");
            return status;
        } else if (activity.getStartDate().compareTo(LocalDateTime.now()) <= 0
                && activity.getEndDate().compareTo(LocalDateTime.now()) >= 0) {
            status.put(5, "进行中");
            return status;
        } else if (activity.getEndDate().compareTo(LocalDateTime.now()) <= 0) {
            if (activity.getSummaryStatus().equals(Activity.SUMMARY_STATUS_YES)) {
                status.put(7, "已结束-活动回顾");
                return status;
            }
            status.put(6, "已结束");
            return status;
        }
        return status;
    }


    @Override
    public String activityStatusAdmin(Activity activity) {
        StringBuilder status = new StringBuilder();
        if (activity.getStartDate().compareTo(LocalDateTime.now()) <= 0
                && activity.getEndDate().compareTo(LocalDateTime.now()) >= 0) {
            status.append("已开始");
            return status.toString();
        } else if (activity.getEndDate().compareTo(LocalDateTime.now()) <= 0) {
            status.append("已结束");
            return status.toString();
        } else if (activity.getSignStartDate().compareTo(LocalDateTime.now()) > 0) {
            status.append("活动预热中");
            return status.toString();
        } else if (activity.getSignStartDate().compareTo(LocalDateTime.now()) <= 0 && activity.getSignEndDate().compareTo(LocalDateTime.now()) >= 0) {
            status.append("报名中");
            return status.toString();
        } else if (activity.getStartDate().compareTo(LocalDateTime.now()) > 0 && activity.getSignEndDate().compareTo(LocalDateTime.now()) < 0) {
            status.append("报名中");
            return status.toString();
        }
        return null;
    }

    @Override
    public Map<Integer, String> activityType(Integer category) {
        Map<Integer, String> map = Maps.newHashMap();
        if (category.equals(Activity.CATEGORY_INNOVATE)) {
            map.put(1, "沙龙会");
            map.put(2, "论坛");
            map.put(3, "讲座");
            map.put(4, "项目路演");
            map.put(5, "创新创业大赛");
            map.put(6, "私董会");
            map.put(7, "分享会");
        } else {
            map.put(1, "讲座");
            map.put(2, "培训班");
            map.put(3, "研修班");
        }
        return map;
    }

    @Override
    public Long getActivityByName(String name) {
        Activity activity = activityDao.findFirstByName(name);
        if (null == activity) {
            throw new HandleException("活动不存在");
        }
        return activity.getId();
    }


    @Override
    public Page<Activity> pageV1(PageParam page, ActivityQueryParam param) {
        Sort sort = new Sort(Sort.Direction.DESC, "createDate");
        PageRequest pageRequest = PageRequest.of(page.getPageIndex(), page.getPageSize(), sort);
        QActivity activity = QActivity.activity;
        Page<Activity> page1 = activityDao.findAll(ExQuery.booleanExpressionBuilder()
                        .and(null != param.getStatus() ? ExQuery.eq(activity.status, param.getStatus()) : null)
                        .and(null != param.getVerify() ? ExQuery.eq(activity.verify, param.getVerify()) : null)
                        .and(null != param.getCategory() ? ExQuery.eq(activity.category, param.getCategory()) : null)
                        .and(null != param.getPublisher() ? ExQuery.eq(activity.publisher, param.getPublisher()) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 1 ? ExQuery.betweenDate(activity.signStartDate, LocalDateTime.now(), null) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 2 ? ExQuery.betweenDate(activity.signStartDate, null, LocalDateTime.now()) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 2 ? ExQuery.betweenDate(activity.signEndDate, LocalDateTime.now(), null) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 3 ? ExQuery.betweenDate(activity.startDate, null, LocalDateTime.now()) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 3 ? ExQuery.betweenDate(activity.endDate, LocalDateTime.now(), null) : null)
                        .and(null != param.getActivityStatus() && param.getActivityStatus() == 4 ? ExQuery.betweenDate(activity.endDate, null, LocalDateTime.now()) : null)
                        .and(null != param.getStartDate() ? ExQuery.betweenDate(activity.startDate, LocalDateTime.parse(param.getStartDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), null) : null)
                        .and(null != param.getEndDate() ? ExQuery.betweenDate(activity.endDate, null, LocalDateTime.parse(param.getEndDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) : null).build()
                , pageRequest);
        return page1;
    }


    @Override
    public Integer countV1(ActivityQueryParam param) {
        QActivity activity = QActivity.activity;
        Long count = activityDao.count(ExQuery.booleanExpressionBuilder()
                .and(null != param.getStatus() ? ExQuery.eq(activity.status, param.getStatus()) : null)
                .and(null != param.getVerify() ? ExQuery.eq(activity.verify, param.getVerify()) : null)
                .and(null != param.getCategory() ? ExQuery.eq(activity.category, param.getCategory()) : null)
                .and(null != param.getPublisher() ? ExQuery.eq(activity.publisher, param.getPublisher()) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 1 ? ExQuery.betweenDate(activity.signStartDate, LocalDateTime.now(), null) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 2 ? ExQuery.betweenDate(activity.signStartDate, null, LocalDateTime.now()) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 2 ? ExQuery.betweenDate(activity.signEndDate, LocalDateTime.now(), null) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 3 ? ExQuery.betweenDate(activity.startDate, null, LocalDateTime.now()) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 3 ? ExQuery.betweenDate(activity.endDate, LocalDateTime.now(), null) : null)
                .and(null != param.getActivityStatus() && param.getActivityStatus() == 4 ? ExQuery.betweenDate(activity.endDate, null, LocalDateTime.now()) : null)
                .and(null != param.getStartDate() ? ExQuery.betweenDate(activity.startDate, LocalDateTime.parse(param.getStartDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), null) : null)
                .and(null != param.getEndDate() ? ExQuery.betweenDate(activity.endDate, null, LocalDateTime.parse(param.getEndDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) : null).build()
        );
        return count.intValue();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityEnrolment(Long activityId, Integer amount) {
        Activity activity = accessObject(activityId);
        if (activity.getEnrolment() <= 0 && amount < 0) {
            return;
        }
        activityDao.updateEnrolment(activityId, amount);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityVerify(Long id, Integer verify, String verifyRemark) {
        Activity activity = accessObject(id);
        activity.setVerify(verify);
        activity.setVerifyDate(LocalDateTime.now());
        String description;
        if (verify.equals(SystemConst.VERIFY_REJECT)) {
            activity.setVerifyRemark(verifyRemark);
            description = String.format("您的活动 %s 审核不通过，点击查看详情跳转相应审核结果页", activity.getName());
        } else {
            description = String.format("您的活动 %s 审核通过，点击查看详情跳转相应审核结果页", activity.getName());
        }
        save(activity);
        if (activity.getPublisher() > 0) {
            mqClient.publish(MQTopics.MEMBER_SEND_MESSAGE, messageService.sendMessageJSON(activity.getPublisher(), Message.MESSAGE_TYPE_VERIFY,
                    "活动发布审核提醒", description, Message.MESSAGE_TARGET_TYPE_ONE_ACTIVITY, activity.getId().toString()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Activity saveActivity(Long publisher, ActivityParamDTO activityParamDTO) {
        Activity activity = convertTo(activityParamDTO, Activity.class);
        activity.setCreateDate(LocalDateTime.now());
        if (publisher > 0) {
            activity.setVerify(SystemConst.VERIFY_AWAIT);
        } else {
            activity.setVerify(SystemConst.VERIFY_ADOPT);
        }
        activity.setVerifyDate(LocalDateTime.now());
        activity.setStatus(SystemConst.STATUS_LOWER_SHELF);
        activity.setIndexType(SystemConst.INDEX_TYPE_NO);
        activity.setCreateDate(LocalDateTime.now());
        activity.setVerifyDate(LocalDateTime.now());
        activity.setPublisher(publisher);
        activity.setSummaryStatus(Activity.SUMMARY_STATUS_NO);
        activity.setEnrolment(0);
        activity.setPrice(AmountConversionUtil.input(activityParamDTO.getPrice()));
        return activityDao.save(activity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateActivity(Long activityId, ActivityParamDTO activityParamDTO) {
        Activity activity = accessObject(activityId);
        activity = ConvertObjectUtil.convertJavaBean(activity, activityParamDTO, true);
        activity.setPrice(AmountConversionUtil.input(activityParamDTO.getPrice()));
        activityDao.save(activity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityUpperShelf(Long activityId) {
        Activity activity = accessObject(activityId);
        if (activity.getStatus().equals(SystemConst.STATUS_UPPER_SHELF)) {
            throw new HandleException("活动已上架，请勿重复操作");
        }
        activity.setStatus(SystemConst.STATUS_UPPER_SHELF);
        activityDao.save(activity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityLowerShelf(Long activityId) {
        Activity activity = accessObject(activityId);
        if (activity.getStatus().equals(SystemConst.STATUS_LOWER_SHELF)) {
            throw new HandleException("活动已下架，请勿重复操作");
        }
        activity.setStatus(SystemConst.STATUS_LOWER_SHELF);
        activityDao.save(activity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityIndexYes(Long activityId) {
        Activity activity = accessObject(activityId);
        if (activity.getIndexType().equals(SystemConst.INDEX_TYPE_YES)) {
            throw new HandleException("活动已推荐至首页，请勿重复操作");
        }
        activity.setIndexType(SystemConst.INDEX_TYPE_YES);
        activityDao.save(activity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activityIndexNo(Long activityId) {
        Activity activity = accessObject(activityId);
        if (activity.getIndexType().equals(SystemConst.INDEX_TYPE_NO)) {
            throw new HandleException("活动已取消推荐至首页，请勿重复操作");
        }
        activity.setIndexType(SystemConst.INDEX_TYPE_NO);
        activityDao.save(activity);
    }

}