package com.duiba.tuia.youtui.web.service.impl;

import cn.com.duiba.wolf.dubbo.DubboResult;
import cn.com.tuia.advert.model.AdvertDirectDto;
import cn.com.tuia.advert.model.DirectAdvertLogReq;
import cn.com.tuia.advert.model.DirectObtainAdvertReq;
import cn.com.tuia.advert.service.IAdvertDirectService;

import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.req.DirectPageReq;
import com.duiba.tuia.youtui.web.service.AdvertService;
import com.duiba.tuia.youtui.web.service.BaseCacheService;
import com.duiba.tuia.youtui.web.tool.CachedKeyUtils;
import com.duiba.tuia.youtui.web.tool.RequestTool;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AdvertServiceImpl extends BaseCacheService implements AdvertService {
    @Resource
    private IAdvertDirectService iAdvertDirectService;

    /**
     * 直投页广告每日点击限制次数
     * 广告id，每日点击限制次数
     */
    private static Map<Long,Integer> advertLimitTimes;
    static{
        advertLimitTimes = Maps.newHashMap();
        advertLimitTimes.put(7998L, 50);

        advertLimitTimes.put(8413L, 100);
        advertLimitTimes.put(8665L, 550);
        advertLimitTimes.put(8695L, 400);
        advertLimitTimes.put(8941L, 2000);
        advertLimitTimes.put(8951L, 50);
        advertLimitTimes.put(8986L, 100);

        advertLimitTimes.put(9247L, 100);
        advertLimitTimes.put(9430L, 120);
        advertLimitTimes.put(9725L, 50);
        advertLimitTimes.put(9782L, 100);
        advertLimitTimes.put(9832L, 700);

        advertLimitTimes.put(10088L, 50);
        advertLimitTimes.put(10374L, 50);

        advertLimitTimes.put(11135L, 250);
        advertLimitTimes.put(11233L, 550);
        advertLimitTimes.put(11265L, 220);
        advertLimitTimes.put(11304L, 50);
        advertLimitTimes.put(11466L, 100);
        advertLimitTimes.put(11599L, 50);
        advertLimitTimes.put(11794L, 300);
        advertLimitTimes.put(11807L, 50);
        advertLimitTimes.put(11991L, 50);

        advertLimitTimes.put(12467L, 20);
        advertLimitTimes.put(12703L, 60);
        advertLimitTimes.put(12830L, 360);

        advertLimitTimes.put(13008L, 150);
        advertLimitTimes.put(13133L, 1000);
        advertLimitTimes.put(13301L, 120);
        advertLimitTimes.put(13329L, 20);
        advertLimitTimes.put(13386L, 20);
        advertLimitTimes.put(13440L, 200);
        advertLimitTimes.put(13454L, 1800);
        advertLimitTimes.put(13494L, 200);
        advertLimitTimes.put(13500L, 20);
        advertLimitTimes.put(13653L, 150);
        advertLimitTimes.put(13676L, 25);
        advertLimitTimes.put(13748L, 100);
        advertLimitTimes.put(13763L, 500);
        advertLimitTimes.put(13820L, 100);
        advertLimitTimes.put(13865L, 850);

        advertLimitTimes.put(14013L, 110);
        advertLimitTimes.put(14180L, 150);
        advertLimitTimes.put(14255L, 500);
        advertLimitTimes.put(14285L, 450);
        advertLimitTimes.put(14301L, 170);
        advertLimitTimes.put(14428L, 100);
        advertLimitTimes.put(14517L, 50);
        advertLimitTimes.put(14558L, 70);
        advertLimitTimes.put(14578L, 10);
        advertLimitTimes.put(14642L, 180);
        advertLimitTimes.put(14663L, 10);
        advertLimitTimes.put(14667L, 100);
        advertLimitTimes.put(14679L, 150);
        advertLimitTimes.put(14726L, 200);
        advertLimitTimes.put(14763L, 50);
        advertLimitTimes.put(14768L, 500);
        
    }

    private List<AdvertDirectDto> filterDailyTimes(List<AdvertDirectDto> dtos) {
        List<AdvertDirectDto> list = Lists.newArrayList();
        if (CollectionUtils.isEmpty(dtos)) {
            return list;
        }

        // 查询受限广告的点击次数
        int day = new DateTime().getDayOfYear();
        Map<Object,Object> advertTimesMap = this.stringRedisTemplate.opsForHash().entries(CachedKeyUtils.getRedisKey(CacheKey.ADVERT_TIMES,day));
        
        dtos.forEach(dto->{
            Integer limitTimes = advertLimitTimes.get(dto.getAdvertId());
            if (limitTimes == null) {//不在受限范围内
                list.add(dto);
            } else {
                Object timesObj = advertTimesMap.get(String.valueOf(dto.getAdvertId()));
                Integer times = timesObj == null ? 0:Integer.valueOf(timesObj.toString());
                if (times < limitTimes) {
                    list.add(dto);
                }

            }
        });

        return list;
    }


    private void advertClickTimes(Long advertId) {
        if (advertLimitTimes.containsKey(advertId)) {
            int day = new DateTime().getDayOfYear();
            String key = CachedKeyUtils.getRedisKey(CacheKey.ADVERT_TIMES,day);
            this.stringRedisTemplate.opsForHash().increment(key, advertId.toString(), 1L);
            stringRedisTemplate.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }
    }

    public List<AdvertDirectDto> getValidAdverts(List<Long> advertIds) throws ActivityException {
        if (CollectionUtils.isEmpty(advertIds)) {
            return new ArrayList<>();
        }
        DubboResult<List<AdvertDirectDto>> dr = this.iAdvertDirectService.getValidAdverts(advertIds);
        if (!dr.isSuccess()) {
            throw new ActivityException(ErrorCode.E0800002);
        }
        return filterDailyTimes(dr.getResult());
    }

    @Override
    public void directAdvertLog(DirectAdvertLogReq req) {
        advertClickTimes(req.getAdvertId());
        DubboResult<Boolean> dr = this.iAdvertDirectService.directAdvert(req);
        if (!dr.isSuccess() || Boolean.FALSE.equals(dr.getResult())) {
            logger.error("直投广告日志接口异常,the msg = {}\n the param= {}", dr.getMsg(),JSONObject.toJSONString(req));
        }
    }

    @Override
    public List<AdvertDirectDto> getValidAdverts(DirectPageReq req,List<Long> advertIds) throws ActivityException {

        if (CollectionUtils.isEmpty(advertIds)) {
            return Collections.emptyList();
        }

        DirectObtainAdvertReq advertReq = new DirectObtainAdvertReq();
        advertReq.setAdvertIds(advertIds);
        advertReq.setConsumerId(req.getConsumerId());
        advertReq.setAppId(req.getAppId());
        advertReq.setDeviceId(req.getDeviceId());
        advertReq.setUa(RequestTool.getUA(req.getUserAgent()));
        advertReq.setIp(req.getIp());
        advertReq.setSlotId(req.getSlotId());
        advertReq.setUserAgent(req.getUserAgent());
        advertReq.setTimestamp(System.currentTimeMillis());
        advertReq.setOs(req.getOs());

        advertReq.setLogExtMap(req.getParamMap());
        DubboResult<List<AdvertDirectDto>> dr = this.iAdvertDirectService.getValidAdverts(advertReq);
        if (!dr.isSuccess()) {
            throw new ActivityException(ErrorCode.E0800002);
        }
        return dr.getResult();
    }

    @Override
    public String getAdvertTimes(Long advertId) {
        return String.valueOf(this.stringRedisTemplate.opsForHash().get(CachedKeyUtils.getRedisKey(CacheKey.ADVERT_TIMES, new DateTime().getDayOfYear()), String.valueOf(advertId)));
    }

}
