package com.seer.teach.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.admin.convert.BooksConvert;
import com.seer.teach.admin.request.BooksQueryReq;
import com.seer.teach.admin.request.BooksSaveReq;
import com.seer.teach.admin.request.BooksUpdateReq;
import com.seer.teach.admin.response.BooksListResp;
import com.seer.teach.admin.response.BooksResp;
import com.seer.teach.common.PageListBean;
import com.seer.teach.common.enums.BookStatusEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.PageConverterUtils;
import com.seer.teach.teacher.module.entity.BooksEntity;
import com.seer.teach.teacher.service.BooksService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Slf4j
@RequiredArgsConstructor
public class BooksAdminService {

    private final BooksService booksService;

    private final BooksConvert booksConvert;
    public PageListBean<BooksListResp> pageList(BooksQueryReq params) {
        Page<BooksEntity> pageParm = new Page<>(params.getPageNo(), params.getPageSize());
        BooksEntity query = BooksConvert.INSTANCE.convertOne(params);
        IPage<BooksEntity> resultPage = booksService.pageList(pageParm, query);
        return PageConverterUtils.convertPageListBean(resultPage, BooksConvert.INSTANCE::convertList);
    }

    /**
     * 新增书籍
     * @param params
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveBooks(BooksSaveReq params) {
        //先查询是否已存在该书籍
        BooksEntity one = booksService.getOne(new LambdaQueryWrapper<BooksEntity>()
                .eq(BooksEntity::getTitle, params.getTitle()));
        AssertUtils.isNull(one, ResultCodeEnum.THE_BOOKS_IS_EXIST);
        BooksEntity entity = booksConvert.convertTwo(params);
        //免费书籍设置价格为0
        if(Objects.equals(entity.getIsFree(),0)){
            entity.setPrice(BigDecimal.ZERO);
        }
        entity.setShelfTime(LocalDateTime.now());
        entity.setDeListTime(null);
        booksService.save(entity);
        log.info("新增书籍成功：{}", params.getTitle());
    }

    /**
     * 上架书籍
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void enSale(List<Integer> ids) {
        AssertUtils.notEmpty(ids, ResultCodeEnum.PLEASE_SELECT_THE_BOOKS_TO_LISTED);
        List<BooksEntity> existList = getBooksEntities(ids);
        List<BooksEntity> toUpdate = new ArrayList<>();
        List<Integer> alreadyOnIds = new ArrayList<>();
        for (BooksEntity entity : existList) {
            if (Objects.equals(entity.getStatus(), BookStatusEnum.ENABLED.getCode())) {
                alreadyOnIds.add(entity.getId());
                continue;
            }
            entity.setStatus(BookStatusEnum.ENABLED.getCode());
            entity.setShelfTime(LocalDateTime.now());
            toUpdate.add(entity);
        }
        if(!toUpdate.isEmpty()){
            booksService.updateBatchById(toUpdate);
        }
        log.info("书籍上架成功");
    }

    /**
     * 下架书籍
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void unSale(List<Integer> ids) {
        AssertUtils.notEmpty(ids, ResultCodeEnum.PLEASE_SELECT_THE_BOOKS_TO_REMOVE);
        List<BooksEntity> existList = getBooksEntities(ids);
        List<BooksEntity> toUpdate = new ArrayList<>();
        List<Integer> alreadyOnIds = new ArrayList<>();
        for (BooksEntity entity : existList) {
            if (Objects.equals(entity.getStatus(), BookStatusEnum.DISABLED.getCode())) {
                alreadyOnIds.add(entity.getId());
                continue;
            }
            entity.setStatus(BookStatusEnum.DISABLED.getCode());
            entity.setDeListTime(LocalDateTime.now());
            toUpdate.add(entity);
        }
        //批量更新未下架的书籍
        if(!toUpdate.isEmpty()){
            booksService.updateBatchById(toUpdate);
        }
        log.info("书籍下架成功");
    }

    /**
     * 校验书籍状态
     * @param ids
     * @return
     */
    @NotNull
    private List<BooksEntity> getBooksEntities(List<Integer> ids) {
        List<Integer> distinctIds = ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        AssertUtils.notEmpty(distinctIds, ResultCodeEnum.THE_BOOKS_ID_NULL);
        List<BooksEntity> existList = booksService.listByIds(distinctIds);
        Set<Integer> existId = existList.stream().map(BooksEntity::getId).collect(Collectors.toSet());
        List<Integer> notFound = distinctIds.stream()
                .filter(id -> !existId.contains(id))
                .collect(Collectors.toList());
        AssertUtils.isTrue(notFound.isEmpty(), ResultCodeEnum.THE_BOOKS_ID_IS_INVALID);
        return existList;
    }

    /**
     * 删除书籍
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteBooks(List<Integer> ids) {
        AssertUtils.notEmpty(ids, ResultCodeEnum.PLEASE_SELECT_THE_BOOKS_TO_DELETED);
        List<BooksEntity> existList = getBooksEntities(ids);
        List<Integer> listedIds = existList.stream()
                .filter(entity -> Objects.equals(entity.getStatus(), 1))
                .map(BooksEntity::getId)
                .collect(Collectors.toList());
        if(!listedIds.isEmpty()){
            AssertUtils.fail(ResultCodeEnum.BOOKS_HAVE_BEEN_LISTED_NOT_ALLOWED_TO_BE_DELETED);
        }
        boolean remove = booksService.removeByIds(ids);
        log.info("删除书籍信息:{}",remove);
    }


    /**
     * 查询书籍详情
     * @param id
     * @return
     */
    public BooksResp detail(Integer id) {
        BooksEntity entity = booksService.getById(id);
        AssertUtils.notNull(entity, ResultCodeEnum.THE_BOOKS_IS_NOT_EXIST);
        BooksResp booksResp = BooksConvert.INSTANCE.convertThree(entity);
        return booksResp;
    }

    /**
     * 修改书籍信息
     * @param req
     */
    public void updateBooksById(BooksUpdateReq req) {
        BooksEntity book = booksService.getById(req.getId());
        AssertUtils.notNull(book, ResultCodeEnum.THE_BOOKS_IS_NOT_EXIST);
        BooksEntity entity = BooksConvert.INSTANCE.convertFour(req);
        if(Objects.equals(entity.getIsFree(),0)){
            entity.setPrice(BigDecimal.ZERO);
        }
        booksService.updateById(entity);
        log.info("修改书籍信息成功：{}", entity);
    }
}
