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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.brframework.commondb.core.AbstractEntityService;
import com.brframework.commondb.core.CommonRepository;
import com.brframework.commonweb.exception.HandleException;
import com.google.common.collect.Lists;
import com.softwarebr.nunu.dao.res.PropertyApplyDao;
import com.softwarebr.nunu.domain.HotDemand;
import com.softwarebr.nunu.entity.res.Invite;
import com.softwarebr.nunu.entity.res.Project;
import com.softwarebr.nunu.entity.res.Property;
import com.softwarebr.nunu.entity.res.PropertyApply;
import com.softwarebr.nunu.globals.SystemConst;
import com.softwarebr.nunu.json.api.center.HotDemandResult;
import com.softwarebr.nunu.service.oper.AreaService;
import com.softwarebr.nunu.service.res.InviteService;
import com.softwarebr.nunu.service.res.ProjectService;
import com.softwarebr.nunu.service.res.PropertyApplyService;
import com.softwarebr.nunu.service.res.PropertyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author lilin
 * @date 2020-02-24 12:19:06
 */

@Slf4j
@Service
public class PropertyApplyServiceImpl extends AbstractEntityService<PropertyApply, Long, Object> implements PropertyApplyService {

    @Autowired
    private PropertyApplyDao propertyApplyDao;

    @Autowired
    private InviteService inviteService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private AreaService areaService;

    @Autowired
    StringRedisTemplate redisTemplate;

    private static final String RESOURCES_HOT_ITEM_KEY = "RESOURCES_HOT_ITEM_KEY";

    @Override
    public CommonRepository<Long, PropertyApply> getRepository() {
        return propertyApplyDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void openPropertyApply(List<Long> ids) {
        for (Long id : ids) {
            PropertyApply apply = accessObject(id);
            apply.setVerify(SystemConst.VERIFY_ADOPT);
            save(apply);
        }
    }

    @Override
    public PropertyApply getPropertyApplyByMember(Integer resourceType, Long targetId, Long proposer) {
        return propertyApplyDao.findTopByResourceTypeAndTargetIdAndProposerAndVerify(resourceType, targetId, proposer, SystemConst.VERIFY_ADOPT);
    }

    @Override
    public Long countByVerifyStatus(Integer resourceType, Long targetId){

        return propertyApplyDao.countByResourceTypeAndTargetIdAndVerify(resourceType, targetId, SystemConst.VERIFY_AWAIT);
    }

    @Override
    public Long[] getAwaitVerifyResourceIds(Integer resourceType){
        List<PropertyApply> propertyApplies = propertyApplyDao.findByResourceTypeAndVerify(resourceType, SystemConst.VERIFY_AWAIT);
        if(propertyApplies.size()>0){
            List<Long> list = propertyApplies.stream().map(PropertyApply::getTargetId).collect(Collectors.toSet()).stream().collect(Collectors.toList());
            return list.toArray(new Long[list.size()]);
        }
        return new Long[]{0L};
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveProperApply(Integer resourceType, Long targetId, Long proposer, String reason) {
        PropertyApply propertyApply = new PropertyApply();
        propertyApply.setProposer(proposer);
        switch (resourceType) {
            case PropertyApply.RESOURCE_TYPE_PROJECT:
                Project project = projectService.accessObject(targetId);
                propertyApply.setPublisher(project.getPublisher());
                propertyApply.setResourceType(resourceType);
                propertyApply.setTargetId(project.getId());
                break;
            case PropertyApply.RESOURCE_TYPE_INVITE:
                Invite invite = inviteService.accessObject(targetId);
                propertyApply.setPublisher(invite.getPublisher());
                propertyApply.setResourceType(resourceType);
                propertyApply.setTargetId(invite.getId());
                break;
            case PropertyApply.RESOURCE_TYPE_PROPERTY:
                Property property = propertyService.accessObject(targetId);
                propertyApply.setPublisher(property.getPublisher());
                propertyApply.setResourceType(resourceType);
                propertyApply.setTargetId(property.getId());
                break;
            default:
                throw new HandleException("资源类型不存在！");
        }
        propertyApply.setCreateDate(LocalDateTime.now());
        propertyApply.setVerify(SystemConst.VERIFY_AWAIT);
        propertyApply.setReason(reason);
        save(propertyApply);
    }

    @Override
    public void hotItemCreate(HotDemand hotDemand) {
        //热门需求储存
        switch (hotDemand.getResourceType()) {
            case PropertyApply.RESOURCE_TYPE_PROJECT:
                projectService.accessObject(hotDemand.getTargetId());
                redisTemplate.opsForZSet().incrementScore(RESOURCES_HOT_ITEM_KEY, JSONObject.toJSONString(hotDemand), 1);
                break;
            case PropertyApply.RESOURCE_TYPE_INVITE:
                inviteService.accessObject(hotDemand.getTargetId());
                redisTemplate.opsForZSet().incrementScore(RESOURCES_HOT_ITEM_KEY, JSONObject.toJSONString(hotDemand), 1);
                break;
            case PropertyApply.RESOURCE_TYPE_PROPERTY:
                propertyService.accessObject(hotDemand.getTargetId());
                redisTemplate.opsForZSet().incrementScore(RESOURCES_HOT_ITEM_KEY, JSONObject.toJSONString(hotDemand), 1);
                break;
            default:
                throw new HandleException("资源类型不存在！");
        }

    }

    @Override
    public List<HotDemandResult> getHotDemand() {
        List<HotDemandResult> demandResults = Lists.newArrayList();
        Set set = redisTemplate.opsForZSet().reverseRange(RESOURCES_HOT_ITEM_KEY, 0, 5);
        if(set.size()>0) {
            ArrayList<String> arrayList = new ArrayList<String>(set);
            for (String object : arrayList) {
                HotDemandResult hotDemandResult = new HotDemandResult();
                HotDemand hotDemand = JSON.parseObject(object, HotDemand.class);
                switch (hotDemand.getResourceType()) {
                    case PropertyApply.RESOURCE_TYPE_PROJECT:
                        Project project = projectService.accessObject(hotDemand.getTargetId());
                        hotDemandResult.setResourceType(hotDemand.getResourceType());
                        hotDemandResult.setTargetId(project.getId());
                        hotDemandResult.setCoverUri(project.getCoverUri());
                        hotDemandResult.setPrice(project.getPrice());
                        hotDemandResult.setProjectName(project.getProjectName());
                        hotDemandResult.setTypeName(projectService.typeMap().get(project.getType()));
                        hotDemandResult.setStatusName(projectService.statusMap().get(project.getType()));
                        break;
                    case PropertyApply.RESOURCE_TYPE_INVITE:
                        Invite invite = inviteService.accessObject(hotDemand.getTargetId());
                        hotDemandResult.setResourceType(hotDemand.getResourceType());
                        hotDemandResult.setTargetId(invite.getId());
                        hotDemandResult.setCoverUri(invite.getCoverUri());
                        hotDemandResult.setCompanyName(invite.getCompanyName());
                        hotDemandResult.setInviteName(invite.getInviteName());
                        hotDemandResult.setStartDate(invite.getStartDate());
                        hotDemandResult.setEndDate(invite.getEndDate());
                        hotDemandResult.setAddress(areaService.addressSplicing(invite.getProvinceId(), invite.getCityId(), invite.getAreaId()));
                        break;
                    case PropertyApply.RESOURCE_TYPE_PROPERTY:
                        Property property = propertyService.accessObject(hotDemand.getTargetId());
                        hotDemandResult.setResourceType(hotDemand.getResourceType());
                        hotDemandResult.setTargetId(property.getId());
                        hotDemandResult.setCoverUri(property.getCoverUri());
                        hotDemandResult.setStartDate(property.getStartDate());
                        hotDemandResult.setEndDate(property.getEndDate());
                        hotDemandResult.setAddress(areaService.addressSplicing(property.getProvinceId(), property.getCityId(), property.getAreaId()));
                        hotDemandResult.setName(property.getName());
                        hotDemandResult.setPrice(property.getPrice());
                        break;
                }
                demandResults.add(hotDemandResult);
            }
        }
        return demandResults;
    }

}