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

import com.brframework.common.utils.ConvertObjectUtil;
import com.brframework.commondb.core.AbstractEntityService;
import com.brframework.commondb.core.CommonRepository;
import com.brframework.commondb.core.ControllerPageHandle;
import com.brframework.commondb.core.ExQuery;
import com.brframework.commondistributed.annotation.DistributedLock;
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.res.ProjectDao;
import com.softwarebr.nunu.dto.res.ProjectParamDTO;
import com.softwarebr.nunu.entity.res.Project;
import com.softwarebr.nunu.entity.res.PropertyApply;
import com.softwarebr.nunu.entity.res.QProject;
import com.softwarebr.nunu.entity.user.Message;
import com.softwarebr.nunu.globals.MQTopics;
import com.softwarebr.nunu.globals.SystemConst;
import com.softwarebr.nunu.json.api.center.ProjectDetailsResult;
import com.softwarebr.nunu.json.api.center.ResProjectQueryParam;
import com.softwarebr.nunu.service.res.ProjectService;
import com.softwarebr.nunu.service.res.PropertyApplyService;
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.util.Map;

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

/**
 * @author lilin
 * @date 2020-02-21 11:47:29
 */

@Slf4j
@Service
@MQConfig
public class ProjectServiceImpl extends AbstractEntityService<Project, Long, Object> implements ProjectService {

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private PropertyApplyService propertyApplyService;

    @Autowired
    private MQClient mqClient;

    @Autowired
    private MessageService messageService;


    @Override
    public CommonRepository<Long, Project> getRepository() {
        return projectDao;
    }

    @Override
    public Map<Integer, String> typeMap() {
        Map<Integer, String> typeMap = Maps.newTreeMap();
        typeMap.put(1, "技术开发");
        typeMap.put(2, "知识产权许可");
        typeMap.put(3, "成果转让");
        typeMap.put(4, "技术咨询");
        typeMap.put(5, "成果转移合作");
        return typeMap;
    }

    @Override
    public Map<Integer, String> statusMap() {
        Map<Integer, String> statusMap = Maps.newTreeMap();
        statusMap.put(1, "征集中");
        statusMap.put(2, "已对接");
        statusMap.put(3, "已终止");
        return statusMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DistributedLock(key = "'LOCK_RESOURCE_PROJECT_' + #projectId")
    public void updateStatus(Long projectId, Integer status) {
        Project project = accessObject(projectId);
        if (!project.getVerify().equals(SystemConst.VERIFY_ADOPT)) {
            throw new HandleException("非法操作");
        }
        projectDao.updateStatus(projectId, status);
    }

    @Override
    public ProjectDetailsResult getProjectDetails(Long id, Long memberId) {
        Project project = accessObject(id);
        ProjectDetailsResult detailsResult = ControllerPageHandle.convertTo(project, ProjectDetailsResult.class);
        if (!detailsResult.getPublicity().equals(SystemConst.PUBLICITY_PUBLIC) && !detailsResult.getPublisher().equals(memberId)) {
            PropertyApply propertyApply = propertyApplyService.getPropertyApplyByMember(PropertyApply.RESOURCE_TYPE_PROJECT, id, memberId);
            if (null == propertyApply) {
                detailsResult.setContactPhone("");
                detailsResult.setContact("");
                detailsResult.setEmail("");
                detailsResult.setDisplay(false);
            }
        }
        return detailsResult;
    }

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

    }

    @Override
    public Page<Project> pageV1(PageParam page, ResProjectQueryParam param) {
        Sort sort = new Sort(Sort.Direction.DESC, "createDate");
        PageRequest pageRequest = PageRequest.of(page.getPageIndex(), page.getPageSize(), sort);
        QProject project = QProject.project;
        Page<Project> page1 = projectDao.findAll(ExQuery.booleanExpressionBuilder()
                .and(null != param.getStatus() ? ExQuery.eq(project.status, param.getStatus()) : null)
                .and(null != param.getType() ? ExQuery.eq(project.type, param.getType()) : null)
                .and(null != param.getMarker() ? ExQuery.eq(project.marker, param.getMarker()) : null)
                .and(null != param.getUpperStatus() ? ExQuery.eq(project.upperStatus, param.getUpperStatus()) : null)
                .and(null != param.getIndexType() ? ExQuery.eq(project.indexType, param.getIndexType()) : null)
                .and(null != param.getPriceMin() ? ExQuery.goe(project.price, AmountConversionUtil.input(param.getPriceMin())) : null)
                .and(null != param.getPriceMax() ? ExQuery.loe(project.price, AmountConversionUtil.input(param.getPriceMax())) : null)
                .and(null != param.getInterview() ? ExQuery.eq(project.price, AmountConversionUtil.input(param.getInterview())) : null)
                .build(), pageRequest);
        return page1;
    }

    @Override
    public Long countProjectByType(Integer type) {
        return projectDao.countByTypeAndMarker(type, SystemConst.MARKER_STATUS_NO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Project saveProject(Long publisher, ProjectParamDTO projectParamDTO) {
        Project project = convertTo(projectParamDTO, Project.class);
        project.setPrice(AmountConversionUtil.input(projectParamDTO.getPrice()));
        project.setCreateDate(LocalDateTime.now());
        project.setVerifyDate(LocalDateTime.now());
        if (publisher > 0) {
            project.setVerify(SystemConst.VERIFY_AWAIT);
        } else {
            project.setVerify(SystemConst.VERIFY_ADOPT);
        }
        project.setPublisher(publisher);
        project.setIndexType(SystemConst.INDEX_TYPE_NO);
        project.setUpperStatus(SystemConst.STATUS_LOWER_SHELF);
        project.setMarker(SystemConst.MARKER_STATUS_NO);
        return projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProject(Long projectId, ProjectParamDTO projectParamDTO) {
        Project project = accessObject(projectId);
        project = ConvertObjectUtil.convertJavaBean(project, projectParamDTO, true);
        project.setPrice(AmountConversionUtil.input(projectParamDTO.getPrice()));
        projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeProjectById(Long projectId) {
        Project project = accessObject(projectId);
        project.setMarker(SystemConst.MARKER_STATUS_YES);
        projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void projectUpperShelf(Long projectId) {
        Project project = accessObject(projectId);
        if (project.getUpperStatus().equals(SystemConst.STATUS_UPPER_SHELF)) {
            throw new HandleException("项目资源已上架，请勿重复操作");
        }
        project.setUpperStatus(SystemConst.STATUS_UPPER_SHELF);
        projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void projectLowerShelf(Long projectId) {
        Project project = accessObject(projectId);
        if (project.getUpperStatus().equals(SystemConst.STATUS_LOWER_SHELF)) {
            throw new HandleException("项目资源已下架，请勿重复操作");
        }
        project.setUpperStatus(SystemConst.STATUS_LOWER_SHELF);
        projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void projectIndexYes(Long projectId) {
        Project project = accessObject(projectId);
        if (project.getIndexType().equals(SystemConst.INDEX_TYPE_YES)) {
            throw new HandleException("项目资源已推荐至首页，请勿重复操作");
        }
        project.setIndexType(SystemConst.INDEX_TYPE_YES);
        projectDao.save(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void projectIndexNo(Long projectId) {
        Project project = accessObject(projectId);
        if (project.getIndexType().equals(SystemConst.INDEX_TYPE_NO)) {
            throw new HandleException("项目资源已取消推荐至首页，请勿重复操作");
        }
        project.setIndexType(SystemConst.INDEX_TYPE_NO);
        projectDao.save(project);
    }
}