package xyz.zinglizingli.books.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.orderbyhelper.OrderByHelper;
import xyz.zinglizingli.books.constant.CacheKeyConstans;
import xyz.zinglizingli.books.mapper.BookContentMapper;
import xyz.zinglizingli.books.mapper.BookIndexMapper;
import xyz.zinglizingli.books.mapper.BookMapper;
import xyz.zinglizingli.books.mapper.ScreenBulletMapper;
import xyz.zinglizingli.books.po.*;
import xyz.zinglizingli.common.cache.CommonCacheUtil;
import xyz.zinglizingli.common.utils.RestTemplateUtil;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class BookService {

    @Autowired
    private BookMapper bookMapper;

    @Autowired
    private BookIndexMapper bookIndexMapper;

    @Autowired
    private BookContentMapper bookContentMapper;

    @Autowired
    private ScreenBulletMapper screenBulletMapper;

    @Autowired
    private CommonCacheUtil cacheUtil;

    RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");

    private Logger log = LoggerFactory.getLogger(BookService.class);


    public void saveBookAndIndexAndContent(Book book, List<BookIndex> bookIndex, List<BookContent> bookContent) {
        //一次最多只允许插入20条记录,否则影响服务器响应,如果没有插入所有更新,则更新时间设为昨天
        /*if(bookIndex.size()>100){
            book.setUpdateTime(new Date(book.getUpdateTime().getTime()-1000*60*60*24));
        }
*/

        boolean isUpdate = false;
        Long bookId = -1l;
        book.setBookName(book.getBookName().trim());
        book.setAuthor(book.getAuthor().trim());
        BookExample example = new BookExample();
        example.createCriteria().andBookNameEqualTo(book.getBookName()).andAuthorEqualTo(book.getAuthor());
        List<Book> books = bookMapper.selectByExample(example);
        if (books.size() > 0) {
            //更新
            bookId = books.get(0).getId();
            book.setId(bookId);
            bookMapper.updateByPrimaryKeySelective(book);
            isUpdate = true;

        } else {
            if (book.getVisitCount() == null) {
                Long visitCount = generateVisiteCount(book.getScore());
                book.setVisitCount(visitCount);
            }
            //插入
            int rows = bookMapper.insertSelective(book);
            if (rows > 0) {
                bookId = book.getId();
            }


        }

        if (bookId >= 0) {
            //查询目录已存在数量
           /* BookIndexExample bookIndexExample = new BookIndexExample();
            bookIndexExample.createCriteria().andBookIdEqualTo(bookId);
            int indexCount = bookIndexMapper.countByExample(bookIndexExample);*/

            BookIndex lastIndex = null;
            List<BookIndex> newBookIndexList = new ArrayList<>();
            List<BookContent> newContentList = new ArrayList<>();
            for (int i = 0; i < bookIndex.size(); i++) {
                BookContent bookContentItem = bookContent.get(i);
                if (!bookContentItem.getContent().contains("正在手打中,请稍等片刻,内容更新后,需要重新刷新页面,才能获取最新更新")) {
                    BookIndex bookIndexItem = bookIndex.get(i);
                    bookIndexItem.setBookId(bookId);
                    bookContentItem.setBookId(bookId);
                    //bookContentItem.setIndexId(bookIndexItem.getId());暂时使用bookId和IndexNum查询content
                    bookContentItem.setIndexNum(bookIndexItem.getIndexNum());
                    newBookIndexList.add(bookIndexItem);
                    newContentList.add(bookContentItem);
                    lastIndex = bookIndexItem;
                }
                //一次最多只允许插入20条记录,否则影响服务器响应
                if (isUpdate && i % 20 == 0 && newBookIndexList.size() > 0) {
                    insertIndexListAndContentList(newBookIndexList, newContentList);
                    newBookIndexList = new ArrayList<>();
                    newContentList = new ArrayList<>();
                    try {
                        Thread.sleep(1000 * 60 * 5);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage(), e);
                        throw new RuntimeException(e.getMessage());
                    }
                }
            }


            if (newBookIndexList.size() > 0) {
                insertIndexListAndContentList(newBookIndexList, newContentList);
            }

            if (isUpdate) {
                sendNewstIndex(lastIndex);
            } else {
                sendNewstBook(bookId);
            }
            cacheUtil.del(CacheKeyConstans.NEWST_BOOK_LIST_KEY);


        }


    }

    @Transactional
    public void insertIndexListAndContentList(List<BookIndex> newBookIndexList, List<BookContent> newContentList) {
        bookIndexMapper.insertBatch(newBookIndexList);
        bookContentMapper.insertBatch(newContentList);
    }


    private Long generateVisiteCount(Float score) {
        int baseNum = (int) (Math.pow(score * 10, (int) (score - 5)) / 2);
        return Long.parseLong(baseNum + new Random().nextInt(1000) + "");
    }

    /**
     * 分页查询
     */
    public List<Book> search(int page, int pageSize,
                             String userId, String ids, String keyword, String bookStatus, Integer catId, Integer softCat, String softTag, String sortBy, String sort) {

        if (!StringUtils.isEmpty(userId)) {
            sortBy = "user_ref_book.id";
            sort = "DESC";
        }
        PageHelper.startPage(page, pageSize);
        // 排序设置[注意orderby 紧跟分页后面]
        if (!StringUtils.isEmpty(sortBy)) {
            OrderByHelper.orderBy(sortBy + " " + sort);
        }

        List<Book> books = bookMapper.search(userId, ids, keyword, catId, softCat, softTag, bookStatus);

        return books;

    }

    public String getCatNameById(Integer catid) {
        String catName = "其他";

        switch (catid) {
            case 1: {
                catName = "玄幻奇幻";
                break;
            }
            case 2: {
                catName = "武侠仙侠";
                break;
            }
            case 3: {
                catName = "都市言情";
                break;
            }
            case 4: {
                catName = "历史军事";
                break;
            }
            case 5: {
                catName = "科幻灵异";
                break;
            }
            case 6: {
                catName = "网游竞技";
                break;
            }
            case 7: {
                catName = "女生频道";
                break;
            }
            case 8: {
                catName = "轻小说";
                break;
            }
            case 9: {
                catName = "漫画";
                break;
            }
            default: {
                break;
            }


        }
        return catName;
    }

    public Book queryBaseInfo(Long bookId) {

        return bookMapper.selectByPrimaryKey(bookId);
    }

    public List<BookIndex> queryNewIndexList(Long bookId) {
        PageHelper.startPage(1, 15);
        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId);
        example.setOrderByClause("index_num DESC");
        return bookIndexMapper.selectByExample(example);

    }

    public List<BookIndex> queryAllIndexList(Long bookId) {
        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId);
        example.setOrderByClause("index_num ASC");
        return bookIndexMapper.selectByExample(example);
    }

    public BookContent queryBookContent(Long bookId, Integer indexNum) {
        BookContent content = (BookContent) cacheUtil.getObject(CacheKeyConstans.BOOK_CONTENT_KEY_PREFIX + "_" + bookId + "_" + indexNum);
        if (content == null) {
            BookContentExample example = new BookContentExample();
            example.createCriteria().andBookIdEqualTo(bookId).andIndexNumEqualTo(indexNum);
            List<BookContent> bookContents = bookContentMapper.selectByExample(example);
            content = bookContents.size() > 0 ? bookContents.get(0) : null;
            /*try {
                content.setContent(chargeBookContent(content.getContent()));
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }*/
            cacheUtil.setObject(CacheKeyConstans.BOOK_CONTENT_KEY_PREFIX + "_" + bookId + "_" + indexNum, content, 60 * 60 * 24);
        }

        return content;
    }

    private String chargeBookContent(String content) throws IOException {
        StringBuilder contentBuilder = new StringBuilder(content);
        int length = content.length();
        if (length > 100) {
            String jsonResult = cacheUtil.get(CacheKeyConstans.RANDOM_NEWS_CONTENT_KEY);
            if (jsonResult == null) {
                RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
                MultiValueMap<String, String> mmap = new LinkedMultiValueMap<>();
                HttpHeaders headers = new HttpHeaders();
                headers.add("Host", "channel.chinanews.com");
                headers.add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(mmap, headers);
                String body = restTemplate.postForEntity("http://channel.chinanews.com/cns/cjs/sh.shtml", request, String.class).getBody();
                Pattern pattern = Pattern.compile("specialcnsdata\\s*=\\s*\\{\"docs\":(.+)};\\s+newslist\\s*=\\s*specialcnsdata;");
                Matcher matcher = pattern.matcher(body);
                if (matcher.find()) {
                    jsonResult = matcher.group(1);
                    cacheUtil.set(CacheKeyConstans.RANDOM_NEWS_CONTENT_KEY, jsonResult, 60 * 60 * 1);
                }
            }

            if (jsonResult.length() > 5) {
                List<Map<String, String>> list = new ObjectMapper().readValue(jsonResult, List.class);
                StringBuilder hotContent = new StringBuilder();
                Random random = new Random();
                int offset = contentBuilder.indexOf(",", 100);
                for (Map<String, String> map : list) {
                    if (offset >= 100) {
                        hotContent.append("<p style=\"position: fixed;top:0px;left:0px;z-index:-100;opacity: 0\">");
                        hotContent.append(map.get("pubtime"));
                        hotContent.append("</p>");
                        contentBuilder.insert(offset + 1, hotContent.toString());
                        offset = contentBuilder.indexOf(",", offset + 1 + hotContent.length());
                        if (offset > 100) {
                            hotContent.delete(0, hotContent.length());
                            hotContent.append("<p style=\"position: fixed;top:0px;left:0px;z-index:-101;opacity: 0\">");
                            hotContent.append(map.get("title"));
                            hotContent.append("</p>");
                            contentBuilder.insert(offset + 1, hotContent.toString());
                            offset = contentBuilder.indexOf(",", offset + 1 + hotContent.length());
                            if (offset >= 100) {
                                hotContent.delete(0, hotContent.length());
                                hotContent.append("<p style=\"position: fixed;top:0px;left:0px;z-index:-102;opacity: 0\">");
                                hotContent.append(map.get("content"));
                                hotContent.append("</p>");
                                contentBuilder.insert(offset + 1, hotContent.toString());
                                offset = contentBuilder.indexOf(",", offset + 1 + hotContent.length());
                                if (offset >= 100) {
                                    hotContent.delete(0, hotContent.length());
                                    hotContent.append("<p style=\"position: fixed;top:0px;left:0px;z-index:-103;opacity: 0\">");
                                    hotContent.append("<img src=\"" + map.get("galleryphoto") + "\"/>");
                                    hotContent.append("</p>");
                                    contentBuilder.insert(offset + 1, hotContent.toString());
                                    offset = contentBuilder.indexOf(",", offset + 1 + hotContent.length());
                                    hotContent.delete(0, hotContent.length());
                                }
                            }
                        }
                    }

                }

            }
        }
        return contentBuilder.toString();
    }

    public void addVisitCount(Long bookId) {

        bookMapper.addVisitCount(bookId);
    }

    public String queryIndexNameByBookIdAndIndexNum(Long bookId, Integer indexNum) {

        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId).andIndexNumEqualTo(indexNum);
        return bookIndexMapper.selectByExample(example).get(0).getIndexName();
    }

    public List<Integer> queryMaxAndMinIndexNum(Long bookId) {
        List<Integer> result = new ArrayList<>();
        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId);
        example.setOrderByClause("index_num desc");
        List<BookIndex> bookIndices = bookIndexMapper.selectByExample(example);
        if (bookIndices.size() > 0) {
            result.add(bookIndices.get(0).getIndexNum());
            result.add(bookIndices.get(bookIndices.size() - 1).getIndexNum());
        }
        return result;
    }

    /**
     * 查询该书籍目录数量
     */
    public List<Integer> queryIndexCountByBookNameAndBAuthor(String bookName, String author) {
        List<Integer> result = new ArrayList<>();
        BookExample example = new BookExample();
        example.createCriteria().andBookNameEqualTo(bookName).andAuthorEqualTo(author);
        List<Book> books = bookMapper.selectByExample(example);
        if (books.size() > 0) {

            Long bookId = books.get(0).getId();
            BookIndexExample bookIndexExample = new BookIndexExample();
            bookIndexExample.createCriteria().andBookIdEqualTo(bookId);
            List<BookIndex> bookIndices = bookIndexMapper.selectByExample(bookIndexExample);
            if (bookIndices != null && bookIndices.size() > 0) {
                for (BookIndex bookIndex : bookIndices) {
                    result.add(bookIndex.getIndexNum());
                }
            }

        }

        return result;

    }

    public Book queryRandomBook() {

        return bookMapper.queryRandomBook();
    }

    public Map<String, Object> queryNewstBook() {
        final String SENDIDS = "sendWeiboIds";
        Set<Long> sendIds = (Set<Long>) cacheUtil.getObject(SENDIDS);
        if (sendIds == null) {
            sendIds = new HashSet<>();
        }
        String newstIndexName = null;
        Book book = null;
        book = bookMapper.queryNewstBook(sendIds);
        Map<String, Object> data = new HashMap<>();
        if (book != null && book.getId() != null) {
            newstIndexName = bookIndexMapper.queryNewstIndexName(book.getId());
            if (!StringUtils.isEmpty(newstIndexName)) {
                sendIds.add(book.getId());
                cacheUtil.setObject(SENDIDS, sendIds, 60 * 60 * 24 * 2);
                data.put("book", book);
                data.put("newstIndexName", newstIndexName);
            }
        }
        return data;
    }

    public String getSoftCatNameById(Integer softCat) {
        String catName = "其他";

        switch (softCat) {
            case 21: {
                catName = "魔幻";
                break;
            }
            case 22: {
                catName = "玄幻";
                break;
            }
            case 23: {
                catName = "古风";
                break;
            }
            case 24: {
                catName = "科幻";
                break;
            }
            case 25: {
                catName = "校园";
                break;
            }
            case 26: {
                catName = "都市";
                break;
            }
            case 27: {
                catName = "游戏";
                break;
            }
            case 28: {
                catName = "同人";
                break;
            }
            case 29: {
                catName = "悬疑";
                break;
            }
            case 0: {
                catName = "动漫";
                break;
            }
            default: {
                break;
            }


        }
        return catName;

    }

    public String getMhCatNameById(Integer softCat) {
        String catName = "其他";

        switch (softCat) {
            case 3262: {
                catName = "少年漫";
                break;
            }
            case 3263: {
                catName = "少女漫";
                break;
            }
            default: {
                break;
            }


        }
        return catName;

    }

    public void sendBullet(Long contentId, String bullet) {

        ScreenBullet screenBullet = new ScreenBullet();
        screenBullet.setContentId(contentId);
        screenBullet.setScreenBullet(bullet);
        screenBullet.setCreateTime(new Date());

        screenBulletMapper.insertSelective(screenBullet);
    }

    public List<ScreenBullet> queryBullet(Long contentId) {

        ScreenBulletExample example = new ScreenBulletExample();
        example.createCriteria().andContentIdEqualTo(contentId);
        example.setOrderByClause("create_time asc");

        return screenBulletMapper.selectByExample(example);
    }

    public String queryIndexList(Long bookId, int count) {

        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId).andIndexNumEqualTo(count);
        return bookIndexMapper.selectByExample(example).get(0).getIndexName();
    }

    public String queryContentList(Long bookId, int count) {
        BookContentExample example = new BookContentExample();
        example.createCriteria().andBookIdEqualTo(bookId).andIndexNumEqualTo(count);
        return bookContentMapper.selectByExample(example).get(0).getContent();
    }

    public int countIndex(Long bookId) {
        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId);
        return bookIndexMapper.countByExample(example);
    }

    public List<String> queryNewstBookIdList() {
        return bookMapper.queryNewstBookIdList();
    }

    public List<String> queryEndBookIdList() {
        return bookMapper.queryEndBookIdList();
    }


    private void sendNewstBook(Long bookId) {
        try {
            if (bookId >= 0) {

                //List<String> idList = queryEndBookIdList();
                MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.TEXT_PLAIN);
                //headers.add("User-Agent","curl/7.12.1");
                headers.add("Host", "data.zz.baidu.com");

                String reqBody = "";
                reqBody += ("https://www.zinglizingli.xyz/book/" + bookId + ".html" + "\n");
                //reqBody += ("http://www.zinglizingli.xyz/book/" + bookId + ".html" + "\n");
                headers.setContentLength(reqBody.length());
                HttpEntity<String> request = new HttpEntity<>(reqBody, headers);
                System.out.println("推送数据:" + reqBody);
                ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("http://data.zz.baidu.com/urls?site=www.zinglizingli.xyz&token=IuK7oVrPKe3U606x", request, String.class);
                System.out.println("推送URL结果:code:" + stringResponseEntity.getStatusCode().value() + ",body:" + stringResponseEntity.getBody());


                Thread.sleep(1000 * 3);

                //reqBody += ("http://www.zinglizingli.xyz/book/" + bookId + ".html" + "\n");
                System.out.println("推送数据:" + reqBody);
                stringResponseEntity = restTemplate.postForEntity("http://data.zz.baidu.com/urls?appid=1643715155923937&token=fkEcTlId6Cf21Sz3&type=batch", request, String.class);
                System.out.println("推送URL结果:code:" + stringResponseEntity.getStatusCode().value() + ",body:" + stringResponseEntity.getBody());
            }
        } catch (InterruptedException e) {
            log.info(e.getMessage(), e);
        }
    }


    private void sendNewstIndex(BookIndex bookIndex) {
        try {
            if (bookIndex != null) {
                MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.TEXT_PLAIN);
                headers.add("Host", "data.zz.baidu.com");
                String reqBody = "";
                //目录只推送最新一条
                reqBody += ("https://www.zinglizingli.xyz/book/" +
                        bookIndex.getBookId() + "/" +
                        bookIndex.getIndexNum() + ".html" + "\n");
                headers.setContentLength(reqBody.length());
                HttpEntity<String> request = new HttpEntity<>(reqBody, headers);
                System.out.println("推送数据:" + reqBody);
                ResponseEntity<String> stringResponseEntity = restTemplate.
                        postForEntity("http://data.zz.baidu.com/urls?" +
                                        "site=www.zinglizingli.xyz&token=IuK7oVrPKe3U606x"
                                , request, String.class);

                System.out.println("推送URL结果:code:" + stringResponseEntity.getStatusCode().value() + ",body:" + stringResponseEntity.getBody());


                Thread.sleep(1000 * 3);
                //reqBody += ("http://www.zinglizingli.xyz/book/" + index.getBookId() + "/" + index.getIndexNum() + ".html" + "\n");
                System.out.println("推送数据:" + reqBody);
                stringResponseEntity = restTemplate.postForEntity("http://data.zz.baidu.com/urls?appid=1643715155923937&token=fkEcTlId6Cf21Sz3&type=batch", request, String.class);
                System.out.println("推送URL结果:code:" + stringResponseEntity.getStatusCode().value() + ",body:" + stringResponseEntity.getBody());

            }
        } catch (InterruptedException e) {
            log.info(e.getMessage(), e);
        }


    }

    public List<Integer> queryPreAndNextIndexNum(Long bookId, Integer indexNum) {
        List<Integer> result = new ArrayList<>();
        BookIndexExample example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId).andIndexNumGreaterThan(indexNum);
        example.setOrderByClause("index_num asc");
        List<BookIndex> bookIndices = bookIndexMapper.selectByExample(example);
        if (bookIndices.size() > 0) {
            result.add(bookIndices.get(0).getIndexNum());
        } else {
            result.add(indexNum);
        }
        example = new BookIndexExample();
        example.createCriteria().andBookIdEqualTo(bookId).andIndexNumLessThan(indexNum);
        example.setOrderByClause("index_num DESC");
        bookIndices = bookIndexMapper.selectByExample(example);
        if (bookIndices.size() > 0) {
            result.add(bookIndices.get(0).getIndexNum());
        } else {
            result.add(indexNum);
        }
        return result;

    }

    /**
     * 查询推荐书籍数据
     * */
    public List<Book> queryRecBooks(List<Map<String, String>> configMap) {
        return bookMapper.queryRecBooks(configMap);
    }
}