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

import com.pcloud.book.base.enums.BookFreezeEnum;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.biz.BookSwitchBiz;
import com.pcloud.book.book.dao.BookTypeDao;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.dto.BookFundDto;
import com.pcloud.book.book.dto.BookTypeDto;
import com.pcloud.book.book.entity.BookSwitch;
import com.pcloud.book.consumer.book.elasticsearch.BookElasticSearchConsr;
import com.pcloud.book.consumer.user.PartyConsr;
import com.pcloud.book.elasticsearch7.domain.dto.param.PlatformSearchDto;
import com.pcloud.book.elasticsearch7.domain.entity.Es7Book;
import com.pcloud.book.elasticsearch7.domain.entity.Es7BookFreeze;
import com.pcloud.book.util.common.Converter;
import com.pcloud.common.core.constant.SystemCode;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.universe.commons.paging.Pagination;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class BookElasticSearchBizImpl {

    @Autowired
    private PartyConsr partyConsr;

    @Autowired
    private BookTypeDao bookTypeDao;

    @Autowired
    private BookElasticSearchConsr bookElasticSearchConsr;

    @Autowired
    private BookBiz bookBiz;

    @Autowired
    private BookSwitchBiz bookSwitchBiz;

    public PageBeanNew<BookDto> getListPage(PlatformSearchDto dto) throws BizException {

        if (!StringUtil.isEmpty(dto.getIsbn()) && StringUtils.isNumeric(dto.getIsbn())) {
            Long isbnNumber = Long.valueOf(dto.getIsbn());
            if(checkIsBookId(isbnNumber)) {
                dto.setBookId(isbnNumber);
                dto.setIsbn(null);
            }
        }
        Pagination<Es7Book> esResult = bookElasticSearchConsr.search(dto);

        List<BookDto> bookList = new ArrayList<>();

        // 获取平台端所有账号用户名
        if (CollectionUtils.isNotEmpty(esResult.getList())) {
            Map<Long, String> pcloudUserMap = partyConsr.getAllUserLoginName(0L, SystemCode.pcloud.code);
            Map<String, BookTypeDto> typeCodeMap = bookTypeDao.getTypeCodeMap();
            List<Long> bookIds = esResult.getList().stream().map(e -> e.getBookId()).collect(Collectors.toList());
            Map<Long, BookSwitch> bookSwitchMap = bookSwitchBiz.mapByBookIds(bookIds);
            esResult.getList().forEach((esBook) -> bookList.add(doBookProcess(esBook, pcloudUserMap, typeCodeMap,bookSwitchMap)));
        }

        PageBeanNew<BookDto> result = new PageBeanNew<>();
        result.setCurrentPage(esResult.getCurrentPage() - 1);
        result.setNumPerPage(esResult.getPageSize());
        result.setRecordList(bookList);
        result.setTotalCount((int) esResult.getTotalCount());
        return result;
    }

    private boolean checkIsBookId(Long isbnNumber) {
        return bookBiz.checkIsBookId(isbnNumber);
    }

    private BookDto doBookProcess(Es7Book esBook, Map<Long, String> pcloudUserMap, Map<String, BookTypeDto> typeCodeMap,Map<Long, BookSwitch> bookSwitchMap) {
        BookDto bookDto = Converter.convert(esBook);

        Integer freezeStatus = BookFreezeEnum.WAIT_FREEZE.value;
        boolean isFundSupport = false;

        Es7BookFreeze bf = findOneByOrderFreezetime(esBook.getBookFreezeList());
        String transferor = bf == null ? null : bf.getTransferor();

        if (CollectionUtils.isNotEmpty(bookDto.getBookFunds())) {
            for (BookFundDto bookFundDto : bookDto.getBookFunds()) {
                transferor = Optional.ofNullable(transferor).orElseGet(bookFundDto::getTransferor);

                Date startTime = bookFundDto.getStartTime();
                Date endTime = bookFundDto.getEndTime();
                if (new Date().before(startTime)) {
                    bookFundDto.setButton(2);
                    freezeStatus = BookFreezeEnum.NO_FREEZE.value;
                } else if (new Date().after(startTime) && new Date().before(endTime)) {
                    bookFundDto.setButton(1);
                    freezeStatus = BookFreezeEnum.NO_FREEZE.value;
                } else {
                    bookFundDto.setButton(0);
                }

                bookFundDto.setOperateUserName(MapUtils.getString(pcloudUserMap,
                        bookFundDto.getLastModifiedUser(),
                        bookFundDto.getOperateUserName()));

                if (new Date().before(endTime)) {
                    isFundSupport = true;
                }
            }
            bookDto.setIsHaveFund(true);
        }
        bookDto.setTransferor(transferor);
        bookDto.setIsFundSupport(isFundSupport);
        bookDto.setFreezeStatus(BooleanUtils.toIntegerObject(findFreezedRecord(esBook.getBookFreezeList()) == null,
                freezeStatus, BookFreezeEnum.FREEZE.value));

        bookDto.setIsHaveAdviser(esBook.getIsAdviserBook() && !esBook.getIsBookAdviserDelete());
        BookSwitch bookSwitch = bookSwitchMap.get(bookDto.getBookId());
        bookDto.setIsBlackBoxEnable(bookSwitch == null ? 0 : bookSwitch.getIsBlackBoxEnable());
        bookDto.setIsResShareEnable(bookSwitch == null ? 0 : bookSwitch.getIsResShareEnable());

        BookTypeDto bookTypeDto = MapUtils.getObject(typeCodeMap, bookDto.getTypeCode());
        bookDto.setTypeName(Optional.ofNullable(bookTypeDto).orElseGet(BookTypeDto::new).getTypeName());

        return bookDto;
    }

    private Es7BookFreeze findOneByOrderFreezetime(List<Es7BookFreeze> fs) {
        if (CollectionUtils.isEmpty(fs)) {
            return null;
        }

        fs.sort(Comparator.comparing(Es7BookFreeze::getFreezetime).reversed());

        return fs.get(0);
    }

    private Es7BookFreeze findFreezedRecord(List<Es7BookFreeze> fs) {
        if (CollectionUtils.isEmpty(fs)) {
            return null;
        }

        return fs.stream().filter((f) -> f.getIsFreeze() == BookFreezeEnum.FREEZE.value.intValue())
                .findFirst().orElse(null);
    }
}
