package cn.stylefeng.team.portal.modular.management.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.constants.MpConstants;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.portal.modular.management.entity.PortalDesign;
import cn.stylefeng.team.portal.modular.management.entity.PortalDesignManager;
import cn.stylefeng.team.portal.modular.management.enums.PortalDesignExceptionEnum;
import cn.stylefeng.team.portal.modular.management.mapper.PortalDesignMapper;
import cn.stylefeng.team.portal.modular.management.pojo.request.PortalDesignRequest;
import cn.stylefeng.team.portal.modular.management.pojo.response.PortalDesignVo;
import cn.stylefeng.team.portal.modular.management.service.PortalDesignManagerService;
import cn.stylefeng.team.portal.modular.management.service.PortalDesignService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PortalDesignServiceImpl extends ServiceImpl<PortalDesignMapper, PortalDesign> implements PortalDesignService {

    @Resource
    private PortalDesignManagerService portalDesignManagerService;

    @Override
    public PageResult<PortalDesignVo> findPage(PortalDesignRequest portalDesignRequest) {

        Page<PortalDesign> page = PageFactory.defaultPage();

        List<PortalDesignManager> currentUserManageList = this.portalDesignManagerService.getCurrentUserPortalManageList();
        if (ObjectUtil.isEmpty(currentUserManageList)) {
            return parseToResult(new ArrayList<>(), page);
        }
        List<Long> totalDesignList = currentUserManageList.stream().map(PortalDesignManager::getDesignId).collect(Collectors.toList());

        LambdaQueryWrapper<PortalDesign> wrapper = createWrapper(portalDesignRequest);
        wrapper.in(PortalDesign::getDesignId, totalDesignList);
        Page<PortalDesign> pageList = this.page(page, wrapper);

        List<PortalDesign> records = pageList.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return parseToResult(new ArrayList<>(), page);
        }
        List<PortalDesignVo> portalDesignVoList = BeanUtil.copyToList(records, PortalDesignVo.class);
        for (PortalDesignVo record : portalDesignVoList) {
            for (PortalDesignManager portalDesignManager : currentUserManageList) {
                if (record.getDesignId().equals(portalDesignManager.getDesignId())) {
                    record.setAuthTypeList(portalDesignManager.getAuthTypeList());
                }
            }
        }
        return parseToResult(portalDesignVoList, page);
    }

    @Override
    public void add(PortalDesignRequest portalDesignRequest) {
        PortalDesign portalDesign = new PortalDesign();

        portalDesign.setDesignName(portalDesignRequest.getDesignName());
        portalDesign.setDesignLogo(portalDesignRequest.getDesignLogo());
        portalDesign.setDescription(portalDesignRequest.getDescription());
        portalDesign.setDesignStatus(portalDesignRequest.getDesignStatus());
        portalDesign.setFldSort(portalDesignRequest.getFldSort());

        this.save(portalDesign);
    }

    @Override
    public void del(PortalDesignRequest portalDesignRequest) {
        PortalDesign portalDesign = this.queryPortalDesign(portalDesignRequest);
        this.removeById(portalDesign.getDesignId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(PortalDesignRequest portalDesignRequest) {
        this.removeByIds(portalDesignRequest.getBatchDeleteIdList());
    }

    @Override
    public void edit(PortalDesignRequest portalDesignRequest) {
        PortalDesign portalDesign = this.queryPortalDesign(portalDesignRequest);

        portalDesign.setDesignName(portalDesignRequest.getDesignName());
        portalDesign.setDesignLogo(portalDesignRequest.getDesignLogo());
        portalDesign.setDescription(portalDesignRequest.getDescription());
        portalDesign.setDesignStatus(portalDesignRequest.getDesignStatus());
        portalDesign.setFldSort(portalDesignRequest.getFldSort());

        this.updateById(portalDesign);
    }

    @Override
    public PortalDesign detail(PortalDesignRequest portalDesignRequest) {
        return this.queryPortalDesign(portalDesignRequest);
    }

    @Override
    public List<PortalDesign> findList(PortalDesignRequest portalDesignRequest) {
        LambdaQueryWrapper<PortalDesign> wrapper = this.createWrapper(portalDesignRequest);
        return this.list(wrapper);
    }

    @Override
    public void updateDesign(PortalDesignRequest portalDesignRequest) {
        LambdaUpdateWrapper<PortalDesign> portalDesignLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        portalDesignLambdaUpdateWrapper.set(PortalDesign::getDesignLayoutJson, portalDesignRequest.getDesignLayoutJson(), MpConstants.TYPE_HANDLER_STRING_JACKSON);
        portalDesignLambdaUpdateWrapper.eq(PortalDesign::getDesignId, portalDesignRequest.getDesignId());
        this.update(portalDesignLambdaUpdateWrapper);
    }

    private PortalDesign queryPortalDesign(PortalDesignRequest portalDesignRequest) {
        PortalDesign portalDesign = this.getById(portalDesignRequest.getDesignId());
        if (ObjectUtil.isEmpty(portalDesign)) {
            throw new ServiceException(PortalDesignExceptionEnum.PORTAL_DESIGN_NOT_EXISTED);
        }
        return portalDesign;
    }

    private LambdaQueryWrapper<PortalDesign> createWrapper(PortalDesignRequest portalDesignRequest) {
        LambdaQueryWrapper<PortalDesign> queryWrapper = new LambdaQueryWrapper<>();

        String searchText = portalDesignRequest.getSearchText();
        if (ObjectUtil.isNotEmpty(searchText)) {
            queryWrapper.nested(i ->
                            i.like(PortalDesign::getDesignName, searchText))
                    .or()
                    .like(PortalDesign::getDescription, searchText);
        }

        Integer designStatus = portalDesignRequest.getDesignStatus();
        queryWrapper.eq(ObjectUtil.isNotNull(designStatus), PortalDesign::getDesignStatus, designStatus);

        return queryWrapper;
    }

    private PageResult<PortalDesignVo> parseToResult(List<PortalDesignVo> list, Page<PortalDesign> page) {
        return PageResultFactory.createPageResult(list, page.getTotal(), Convert.toInt(page.getSize()), Convert.toInt(page.getCurrent()));
    }

}
