package com.pcloud.book.record.biz.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.pcloud.book.applet.biz.AppletBookClassifyBiz;
import com.pcloud.book.applet.dto.AppletBookClassifyDTO;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.consumer.analysisengine.BookScanCountConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.AgentConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.record.biz.BookBrowseRecordBiz;
import com.pcloud.book.record.dao.BookBrowseRecordDAO;
import com.pcloud.book.record.dao.MapDataDAO;
import com.pcloud.book.record.entity.AreaStatistics;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.book.record.entity.BookDetail;
import com.pcloud.book.record.entity.BookMapStatistics;
import com.pcloud.book.record.entity.ClassifyStatistics;
import com.pcloud.book.record.entity.IpData;
import com.pcloud.book.record.entity.IpData4Third;
import com.pcloud.book.record.entity.IpResponse;
import com.pcloud.book.record.entity.MapData;
import com.pcloud.book.record.entity.RegionMap;
import com.pcloud.book.record.mapper.IpDataMapper;
import com.pcloud.book.record.mapper.RegionMapMapper;
import com.pcloud.book.util.common.HttpUtils;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.json.JSONUtils;
import com.pcloud.common.utils.string.StringUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @ClassName com.pcloud.book.record.biz.impl.BookBrowseRecordBizImpl
 * @Author 吴博
 * @Description 读者书籍埋点记录
 * @Date 2020/6/12 16:04
 * @Version 1.0
 **/
@Service
@Slf4j
public class BookBrowseRecordBizImpl implements BookBrowseRecordBiz {


    @Autowired
    private ChannelConsr channelConsr;
    @Autowired
    private BookAdviserDao bookAdviserDao;
    @Autowired
    private BookBrowseRecordDAO bookBrowseRecordDAO;
    @Autowired
    private AppletBookClassifyBiz appletBookClassifyBiz;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private MapDataDAO mapDataDAO;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private RegionMapMapper regionMapMapper;
    @Autowired
    private IpDataMapper ipDataMapper;
    @Autowired
    private BookScanCountConsr bookScanCountConsr;
    @Value("${ip.appcode}")
    private String appCode;

    @Override
    @ParamLog("读者书籍埋点记录")
    public void addBookRecord(BookBrowseRecord bookBrowseRecord) {
        Long sceneId = bookBrowseRecord.getSceneId();
        if (null == sceneId) {
            return;
        }
        // 先判断书籍是否存在
        Long bookId = channelConsr.getBookId4SceneId(sceneId);
        if (null == bookId) {
            return;
        }
        bookBrowseRecord.setBookId(bookId);
        addBookRecord4BookId(bookBrowseRecord);
    }

    @Override
    @ParamLog("读者书籍埋点记录")
    public void addBookRecord4BookId(BookBrowseRecord bookBrowseRecord) {
        BookAdviserDto bookAdviserDto = bookAdviserDao.getOneMainBook(bookBrowseRecord.getBookId());
        BookDto bookDto = bookDao.getBaseById(bookBrowseRecord.getBookId());
        if (null == bookAdviserDto || null == bookDto) {
            return;
        }
        Long agentId  = null;
        bookBrowseRecord.setBookAdviserId(bookAdviserDto.getBookAdviserId());
        bookBrowseRecord.setBookName(bookDto.getBookName());
        bookBrowseRecord.setIsbn(bookDto.getIsbn());
        if (null != bookAdviserDto.getAdviserId()) {
            agentId = adviserConsr.getAgentIdByAdviser(bookAdviserDto.getAdviserId());
        }
        bookBrowseRecord.setAdviserId(bookAdviserDto.getAdviserId());
        bookBrowseRecord.setAgentId(agentId);
        Long firstClassifyId = null == bookAdviserDto.getTempletId() ? 0 : bookAdviserDto.getTempletId();
        Long secondClassifyId = null == bookAdviserDto.getSecondTempletId() ? 0 : bookAdviserDto.getSecondTempletId();
        Long thirdClassifyId = null == bookAdviserDto.getThirdTempletId() ? 0 : bookAdviserDto.getThirdTempletId();
        Long graLabelId = null == bookAdviserDto.getGraLabelId() ? 0 : bookAdviserDto.getGraLabelId();
        Long subLabelId = null == bookAdviserDto.getSubLabelId() ? 0 : bookAdviserDto.getSubLabelId();
        Long bookClassifyId = null;
        // 根据一级分类id获取书籍分类id
        if (Objects.equals(0, firstClassifyId)) {
            bookClassifyId = 0L;
        } else {
            bookClassifyId = appletBookClassifyBiz.getAppletBookClassifyId(firstClassifyId);
        }
        bookBrowseRecord.setFirstClassifyId(firstClassifyId);
        bookBrowseRecord.setSecondClassifyId(secondClassifyId);
        bookBrowseRecord.setThirdClassifyId(thirdClassifyId);
        bookBrowseRecord.setGraLabelId(graLabelId);
        bookBrowseRecord.setSubLabelId(subLabelId);
        bookBrowseRecord.setBookClassifyId(bookClassifyId);
        // 根据ip获取省份和城市
        getAreaByIP(bookBrowseRecord);
        log.info("插入的数据是：{}", bookBrowseRecord);
        if (null == bookBrowseRecord || StringUtil.isEmpty(bookBrowseRecord.getCityCode())){
            return;
        }
        bookBrowseRecordDAO.insert(bookBrowseRecord);
    }

    @Override
    @ParamLog("获取全国的书刊统计数据")
    public List<BookMapStatistics> getBookCount4Country(String regionCode, Long agentId) {
        List<Long> adviserIds = new ArrayList<>();
        if (null != agentId && agentId>0){
            adviserIds = adviserConsr.getByAgentId(agentId);
        }
        return bookBrowseRecordDAO.getBookCount4Country(regionCode, adviserIds);
    }

    @Override
    @ParamLog("获取某个地区的分类统计信息")
    public AreaStatistics getAreaStatistics(String regionCode, Integer areaCode, Long agentId) {
        List<Long> adviserIds = new ArrayList<>();
        if (null != agentId && agentId>0){
            adviserIds = adviserConsr.getByAgentId(agentId);
        }
        AreaStatistics areaStatistics = bookBrowseRecordDAO.getAreaStatistics(regionCode, areaCode, adviserIds);
        if (null == areaStatistics) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"数据库没有数据");
        }
        List<ClassifyStatistics> classifyStatisticsList = bookBrowseRecordDAO.getClassifyStatistics(regionCode, areaCode, adviserIds);
        areaStatistics.setClassifyStatisticsList(classifyStatisticsList);
        return areaStatistics;
    }

    @Override
    @ParamLog(value = "获取区域详情", isAfterReturn = false)
    public PageBeanNew<BookDetail> getBookDetail(String regionCode, Integer areaCode, PageParam pageParam,
            String bookName, Long agentId, Long bookClassifyId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("regionCode", regionCode);
        paramMap.put("areaCode", areaCode);
        paramMap.put("bookName", bookName);
        paramMap.put("agentId", agentId);
        paramMap.put("bookClassifyId", bookClassifyId);
        PageBeanNew<BookDetail> pageBeanNew = bookBrowseRecordDAO.listPageNew(pageParam, paramMap, "getBookDetail");
        if (null != pageBeanNew && !ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            List<BookDetail> bookDetails = pageBeanNew.getRecordList();
            List<Long> bookAdviserIds = bookDetails.stream().map(e -> e.getBookAdviserId()).collect(Collectors.toList());
            List<Long> bookClassifyIds = bookDetails.stream().map(e -> e.getBookClassifyId()).collect(Collectors.toList());
            List<Long> adviserIds = bookDetails.stream().map(e -> e.getAdviserId()).collect(Collectors.toList());
            List<Long> agentIds = bookDetails.stream().map(e -> e.getAgentId()).collect(Collectors.toList());
            if (ListUtils.isEmpty(bookAdviserIds)) {
                return new PageBeanNew<>(pageParam.getPageNum(), pageBeanNew.getNumPerPage(), new ArrayList<>());
            }
            //获取书刊社群相关信息
            Map<Long, BookGroupDTO> bookGroupDTOMap = bookGroupDao.getBookBaseInfoByAdviserBookIds(bookAdviserIds);
            //获取分类标签
            Map<Long, AppletBookClassifyDTO> appletBookClassifyDTOMap = new HashMap<>();
            if (!ListUtils.isEmpty(bookClassifyIds)) {
                appletBookClassifyDTOMap = appletBookClassifyBiz.getBookClassifyByIds(bookClassifyIds);
            }
            //获取编辑以及出版社名称
            Map<Long, String> adviserMap =  new HashMap<>();
            Map<Long, String> agentMap = new HashMap<>();
            if (!ListUtils.isEmpty(adviserIds)){
                adviserMap = adviserConsr.getNames(adviserIds);
            }
            if (!ListUtils.isEmpty(agentIds)) {
                agentMap = agentConsr.getNames(agentIds);
            }
            for (BookDetail bookDetail : bookDetails) {
                if (MapUtils.isNotEmpty(bookGroupDTOMap) && bookGroupDTOMap.containsKey(bookDetail.getBookAdviserId())
                        && null != bookGroupDTOMap.get(bookDetail.getBookAdviserId())) {
                    BookGroupDTO bookGroupDTO = bookGroupDTOMap.get(bookDetail.getBookAdviserId());
                    bookDetail.setBookGroupName(bookGroupDTO.getGroupQrcodeName());
                    bookDetail.setCreateTime(bookGroupDTO.getCreateTime());
                    bookDetail.setBookGroupUrl(bookGroupDTO.getGroupQrcodeUrl());
                }
                if (MapUtils.isNotEmpty(adviserMap) && adviserMap.containsKey(bookDetail.getAdviserId())
                        && null != adviserMap.get(bookDetail.getAdviserId())) {
                    bookDetail.setAdviserName(adviserMap.get(bookDetail.getAdviserId()));
                }
                if (MapUtils.isNotEmpty(agentMap) && agentMap.containsKey(bookDetail.getAgentId())
                        && null != agentMap.get(bookDetail.getAgentId())) {
                    bookDetail.setAgentName(agentMap.get(bookDetail.getAgentId()));
                }
                if (MapUtils.isNotEmpty(appletBookClassifyDTOMap) && appletBookClassifyDTOMap.containsKey(bookDetail.getBookClassifyId())
                        && null != appletBookClassifyDTOMap.get(bookDetail.getBookClassifyId())) {
                    bookDetail.setBookClassifyName(appletBookClassifyDTOMap.get(bookDetail.getBookClassifyId()).getClassifyName());
                }
            }
        }
        return pageBeanNew;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addJsonData() {
        String filepath = "C:\\Users\\Administrator\\Documents\\WXWork\\1688851019478260\\Cache\\File\\2020-06\\coordinate\\coordinate";
        List<MapData> mapDatas = new ArrayList<>();
        File file = new File(filepath);
        if (!file.isDirectory()) {
            System.out.println("文件");
            System.out.println("path=" + file.getPath());
            System.out.println("absolutepath=" + file.getAbsolutePath());
            System.out.println("name=" + file.getName());

        } else if (file.isDirectory()) {
            System.out.println("文件夹");
            String[] filelist = file.list();
            for (int i = 0; i < filelist.length; i++) {
                File readfile = new File(filepath + "\\" + filelist[i]);
                String fileName = readfile.getName();
                String[] fileNames = fileName.split("\\.");
                String code = fileNames[0];
                StringBuilder line= new StringBuilder();
                try{
                    BufferedReader in=new BufferedReader(new FileReader(readfile.getAbsolutePath()));
                    while(in.readLine() != null){
                        line.append(in.readLine());
                    }
                    in.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch(IOException e){
                    e.printStackTrace();
                }
                MapData mapData = new MapData();
                mapData.setRegionCode(code);
                mapData.setContent(line.toString());
                mapDatas.add(mapData);
                mapDataDAO.insert(mapData);
            }
        }
    }
    @Override
    public PageBeanNew<MapData> getJsonData(String regionCode, Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("regionCode", regionCode);
        return mapDataDAO.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getJsonData");
    }

    @Override
    @ParamLog("获取地图数据")
    public Map<String, List<RegionMap>> getCitysByPY(String keyword) {
        Map<String, List<RegionMap>> regionMap = new HashMap<>(30);
        //全部数据从缓存中取
        if (StringUtil.isEmpty(keyword)) {
            String redisKey = BookConstant.BOOK_CITY_MAP;
            Map<String, String> regionStringMap = JedisClusterUtils.hgetAll(redisKey);
            if (MapUtil.isNotEmpty(regionStringMap)) {
                Map<String, List<RegionMap>> localRegionMap = regionMap;
                regionStringMap.forEach((key, value) -> {
                    List<RegionMap> regionMapList = JSONArray.parseArray(value, RegionMap.class);
                    localRegionMap.put(key, regionMapList);
                });
                log.info("全部数据从缓存中取:getCitysByPY");
                return localRegionMap;
            } else {
                List<RegionMap>  regionMaps = regionMapMapper.getCitysByPY(null);
                if (!ListUtils.isEmpty(regionMaps)){
                    regionMap = regionMaps.stream().collect(Collectors.groupingBy(RegionMap::getAlphabet));
                }
                if (MapUtil.isNotEmpty(regionMap)) {
                    Map<String, String> localRegionStringMap = new HashMap<>(30);
                    regionMap.forEach((key, value) -> {
                        String  regionString = JSONUtils.toJsonString(value);
                        localRegionStringMap.put(key, regionString);
                    });
                    JedisClusterUtils.hmset(redisKey, localRegionStringMap, BookConstant.DEFAULT_DAY_TIMEOUT);
                }
                return regionMap;
            }
        } else {
            List<RegionMap>  regionMaps = regionMapMapper.getCitysByPY(keyword);
            if (!ListUtils.isEmpty(regionMaps)){
                regionMap = regionMaps.stream().collect(Collectors.groupingBy(RegionMap::getAlphabet));
            }
            return regionMap;
        }
    }

    @Override
    @ParamLog("处理旧的书刊读者数据")
    public void handleOldData() {

    }

    @Override
    @ParamLog("根据cityCodes获取相应城市")
    public Map<String, RegionMap> getCitysByCodes(List<String> cityCodes) {
        if (ListUtils.isEmpty(cityCodes)){
            return new HashMap<>();
        }
        return regionMapMapper.getCitysByCodes(cityCodes);
    }

    @Override
    @ParamLog("通过ip获取城市")
    public BookBrowseRecord getCityByIP(String ip) {
        BookBrowseRecord bookBrowseRecord = new BookBrowseRecord();
        bookBrowseRecord.setIp(ip);
        this.getAreaByIP(bookBrowseRecord);
        return bookBrowseRecord;
    }

    @Override
    public Map<String, String> getCitiesByIp(List<String> ips) {
        Map<String, String> map = new HashMap<>();
        List<IpData> ipData = ipDataMapper.listCityByIp(ips);
        if (!CollUtil.isEmpty(ipData)) {
            map = ipData.stream().collect(Collectors.toMap(IpData::getIp, IpData::getCity));
            Map<String, String> finalMap = map;
            ips = ips.stream().filter(item -> StrUtil.isEmpty(finalMap.get(item))).collect(Collectors.toList());
        }
        for (String ip : ips) {
            map.put(ip, getCityByIp(ip));
        }
        return map;
    }

    private String getCityByIp(String ip) {
        IpData ipData = new IpData();
        ipData.setIp(ip);
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "APPCODE " + appCode);
        Map<String, String> querys = new HashMap<>();
        querys.put("ip", ip);

        try {
            HttpResponse response = HttpUtils.doGet("https://api01.aliyun.venuscn.com", "/ip", "GET", headers, querys);
            log.info("查询ip返回的数据是response：{}", response);
            String entityString = EntityUtils.toString(response.getEntity());
            IpResponse ipResponse = null;
            if (StringUtil.isEmpty(entityString)) {
                return null;
            }
            ipResponse = JSONUtils.jsonToBean(entityString, IpResponse.class);
            if (null == ipResponse || null == ipResponse.getData()) {
                return null;
            }
            IpData4Third ipData4Third = ipResponse.getData();
            if (!Objects.equals("200", ipResponse.getRet())) {
                return null;
            }
            if (null == ipData4Third || null == ipData4Third.getCity_id()) {
                return null;
            }
            ipData = new IpData();
            ipData.setIp(ip);
            ipData.setRegion(ipData4Third.getRegion());
            ipData.setRegionId(ipData4Third.getRegion_id());
            ipData.setCity(ipData4Third.getCity());
            ipData.setCityId(ipData4Third.getCity_id());
            ipDataMapper.insert(ipData);
        } catch (Exception e) {
            log.error("获取ip失败，ip：{}", ip);
            return null;
        }
        return ipData.getCity();
    }

    private void getAreaByIP(BookBrowseRecord bookBrowseRecord) {
        String host = "https://api01.aliyun.venuscn.com";
        String path = "/ip";
        String method = "GET";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appCode);
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("ip", bookBrowseRecord.getIp());
        //先从数据库查询，没有再查询第三方
        IpData ipData = ipDataMapper.selectByIp(bookBrowseRecord.getIp());
        if (null == ipData) {
            try {
                HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
                log.info("查询ip返回的数据是response：{}", response);
                String entityString = EntityUtils.toString(response.getEntity());
                IpResponse ipResponse = null;
                if (StringUtil.isEmpty(entityString)) {
                    return;
                }
                ipResponse = JSONUtils.jsonToBean(entityString, IpResponse.class);
                if (null == ipResponse || null == ipResponse.getData()) {
                    return;
                }
                IpData4Third ipData4Third = ipResponse.getData();
                if (!Objects.equals("200", ipResponse.getRet())) {
                    return;
                }
                if (null == ipData4Third || null == ipData4Third.getCity_id()) {
                    return;
                }
                ipData = new IpData();
                ipData.setIp(bookBrowseRecord.getIp());
                ipData.setRegion(ipData4Third.getRegion());
                ipData.setRegionId(ipData4Third.getRegion_id());
                ipData.setCity(ipData4Third.getCity());
                ipData.setCityId(ipData4Third.getCity_id());
                ipDataMapper.insert(ipData);
            } catch (Exception e) {
                log.warn("获取ip失败，ip：{}", bookBrowseRecord.getIp(), e);
            }
        }
        if (null != ipData) {
            bookBrowseRecord.setProvince(ipData.getRegion());
            bookBrowseRecord.setProvinceCode(ipData.getRegionId());
            bookBrowseRecord.setCity(ipData.getCity());
            bookBrowseRecord.setCityCode(ipData.getCityId());
        }
    }
}