package cn.hanghui.outapi.platform.tenant.service.impl;

import cn.hanghui.outapi.platform.common.entity.po.Account;
import cn.hanghui.outapi.platform.common.entity.rest.RestResult;
import cn.hanghui.outapi.platform.common.utils.Preconditions;
import cn.hanghui.outapi.platform.tenant.entity.dto.SceneDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.UserLibDto;
import cn.hanghui.outapi.platform.tenant.entity.enums.AuthModuleTypeEnum;
import cn.hanghui.outapi.platform.tenant.entity.po.Device;
import cn.hanghui.outapi.platform.tenant.entity.po.Scene;
import cn.hanghui.outapi.platform.tenant.entity.po.UserLib;
import cn.hanghui.outapi.platform.tenant.mapper.DeviceMapper;
import cn.hanghui.outapi.platform.tenant.mapper.SceneMapper;
import cn.hanghui.outapi.platform.tenant.mapper.UserLibMapper;
import cn.hanghui.outapi.platform.tenant.service.SceneService;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author shisl
 * @package cn.hanghui.outapi.platform.tenant.service.impl
 * @class SceneServiceImpl
 * @date 2023/5/4 上午9:49
 * @description 场景和用户库管理
 */
@Service
@Slf4j
public class SceneServiceImpl implements SceneService {

    @Resource
    private SceneMapper sceneMapper;

    @Resource
    private UserLibMapper userLibMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private CommonImpl commonImpl;


    @Override
    public RestResult<Boolean> addScene(SceneDto dto) {
        if (checkTrade(dto)) { //校验场景参数是否存在
            return RestResult.error("场景参数已存在");
        }
        if (dto.getId() != null) {
            Scene scene = sceneMapper.selectById(dto.getId());
            if (scene == null || scene.getIsDeleted()) {
                return RestResult.error("数据不存在或已删除");
            }
            scene.setSceneName(dto.getSceneName());
            scene.setTrade(dto.getTrade());
            scene.setUpdateTime(new Date());
            sceneMapper.updateById(scene);
        } else {
            Scene scene = new Scene();
            scene.setSceneName(dto.getSceneName());
            scene.setTrade(dto.getTrade());
            scene.setIsDeleted(Boolean.FALSE);
            scene.setCreateTime(new Date());
            scene.setUpdateTime(new Date());
            scene.setVersion(1);
            sceneMapper.insert(scene);
        }
        return RestResult.ok(Boolean.TRUE);
    }

    private boolean checkTrade(SceneDto dto) {
        List<Scene> scenes = sceneMapper.selectList(Wrappers.lambdaQuery(Scene.class).eq(Scene::getTrade, dto.getTrade()).eq(Scene::getIsDeleted, Boolean.FALSE));
        if (scenes != null && scenes.size() > 0) {
            if (dto.getId() == null) {
                return Boolean.TRUE;
            } else {
                List<Long> ids = scenes.stream().map(Scene::getId).collect(Collectors.toList());
                if (!ids.contains(dto.getId())) {
                    return Boolean.TRUE;
                }
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public RestResult<Boolean> delScene(Long id) {
        Scene scene = sceneMapper.selectById(id);
        if (scene == null || scene.getIsDeleted() == null || scene.getIsDeleted()) {
            return RestResult.error("数据不存在或已删除");
        }

        //check是否有使用
        if (checkSceneUsed(id)) {
            return RestResult.error("场景使用中不可删除");
        }

        scene.setIsDeleted(Boolean.TRUE);
        scene.setUpdateTime(new Date());
        sceneMapper.updateById(scene);
        return RestResult.ok(Boolean.TRUE);
    }

    private Boolean checkSceneUsed(Long sceneId) {
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getIsDeleted, Boolean.FALSE).eq(Device::getSceneId, sceneId);
        Long count = deviceMapper.selectCount(wrapper);
        return (count != null && count.longValue() > 0l) ? Boolean.TRUE : Boolean.FALSE;
    }

    @Override
    public RestResult<IPage<SceneDto>> pageScene(SceneDto dto) {
        Page<Scene> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<Scene> wrapper = new LambdaQueryWrapper<>();
        if (dto.getSceneName() != null && !"".equals(dto.getSceneName().trim())) {
            wrapper.like(Scene::getSceneName, dto.getSceneName().trim());
        }
        if (dto.getTrade() != null && !"".equals(dto.getTrade().trim())) {
            wrapper.like(Scene::getTrade, dto.getTrade().trim());
        }
        wrapper.eq(Scene::getIsDeleted, Boolean.FALSE).orderByDesc(Scene::getId);
        IPage<Scene> iPage = sceneMapper.selectPage(page, wrapper);
        IPage<SceneDto> convert = iPage.convert(t -> {
            SceneDto item = BeanUtil.copyProperties(t, SceneDto.class);
            return item;
        });
        return RestResult.ok(convert);
    }

    @Override
    public RestResult<Boolean> addUserLib(UserLibDto dto) {

        if (checkGroupId(dto)) { //校验⽤⼾库ID是否存在
            return RestResult.error("⽤⼾库ID已存在");
        }

        if (dto.getId() != null) {
            UserLib userLib = userLibMapper.selectById(dto.getId());
            if (userLib == null || userLib.getIsDeleted()) {
                return RestResult.error("数据不存在或已删除");
            }
            userLib.setGroupId(dto.getGroupId());
            userLib.setUserLibName(dto.getUserLibName());
            userLib.setUpdateTime(new Date());
            userLibMapper.updateById(userLib);
        } else {
            UserLib userLib = new UserLib();
            userLib.setGroupId(dto.getGroupId());
            userLib.setUserLibName(dto.getUserLibName());
            userLib.setIsDeleted(Boolean.FALSE);
            userLib.setCreateTime(new Date());
            userLib.setUpdateTime(new Date());
            userLib.setVersion(1);
            userLibMapper.insert(userLib);
        }
        return RestResult.ok(Boolean.TRUE);
    }

    private boolean checkGroupId(UserLibDto dto) {
        List<UserLib> userLibs = userLibMapper.selectList(Wrappers.lambdaQuery(UserLib.class).eq(UserLib::getGroupId, dto.getGroupId()).eq(UserLib::getIsDeleted, Boolean.FALSE));
        if (userLibs != null && userLibs.size() > 0) {
            if (dto.getId() == null) {
                return Boolean.TRUE;
            } else {
                List<Long> ids = userLibs.stream().map(UserLib::getId).collect(Collectors.toList());
                if (!ids.contains(dto.getId())) {
                    return Boolean.TRUE;
                }
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public RestResult<Boolean> delUserLib(Long id) {
        UserLib userLib = userLibMapper.selectById(id);
        if (userLib == null || userLib.getIsDeleted()) {
            return RestResult.error("数据不存在或已删除");
        }

        //check是否有使用
        if (checkUserLibUsed(id)) {
            return RestResult.error("用户库使用中不可删除");
        }

        userLib.setIsDeleted(Boolean.TRUE);
        userLib.setUpdateTime(new Date());
        userLibMapper.updateById(userLib);
        return RestResult.ok(Boolean.TRUE);
    }

    private boolean checkUserLibUsed(Long userLibId) {
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getIsDeleted, Boolean.FALSE).eq(Device::getUserLibId, userLibId);
        Long count = deviceMapper.selectCount(wrapper);
        return (count != null && count.longValue() > 0l) ? Boolean.TRUE : Boolean.FALSE;
    }

    @Override
    public RestResult<IPage<UserLibDto>> pageUserLib(UserLibDto dto) {
        Page<UserLib> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<UserLib> wrapper = new LambdaQueryWrapper<>();
        if (dto.getGroupId() != null && !"".equals(dto.getGroupId().trim())) {
            wrapper.like(UserLib::getGroupId, dto.getGroupId().trim());
        }
        if (dto.getUserLibName() != null && !"".equals(dto.getUserLibName().trim())) {
            wrapper.like(UserLib::getUserLibName, dto.getUserLibName().trim());
        }
        wrapper.eq(UserLib::getIsDeleted, Boolean.FALSE).orderByDesc(UserLib::getId);
        IPage<UserLib> iPage = userLibMapper.selectPage(page, wrapper);
        IPage<UserLibDto> convert = iPage.convert(t -> {
            UserLibDto item = BeanUtil.copyProperties(t, UserLibDto.class);
            return item;
        });
        return RestResult.ok(convert);
    }

    @Override
    public RestResult<List<UserLibDto>> serLibList() {
        LambdaQueryWrapper<UserLib> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserLib::getIsDeleted, Boolean.FALSE).orderByDesc(UserLib::getId);
        List<UserLib> list = userLibMapper.selectList(wrapper);
        List<UserLibDto> userLibDtos = BeanUtil.copyToList(list, UserLibDto.class);
        return RestResult.ok(userLibDtos);
    }

    @Override
    public RestResult<List<UserLibDto>> getUserLibList(Account account, AuthModuleTypeEnum hhfaceUserLib) {
        List<Long> userLibIds = commonImpl.getAuthModuleIds(account, hhfaceUserLib);
        if (Preconditions.isBlank(userLibIds)) {
            return RestResult.ok(Collections.emptyList());
        }
        List<UserLib> list = userLibMapper.selectList(Wrappers.lambdaQuery(UserLib.class).in(UserLib::getId, userLibIds).eq(UserLib::getIsDeleted, Boolean.FALSE));
        List<UserLibDto> userLibDtos = BeanUtil.copyToList(list, UserLibDto.class);
        return RestResult.ok(userLibDtos != null ? userLibDtos : Collections.emptyList());
    }
}
