package com.zhongshu.card.server.core.service.scene;

import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.zhongshu.card.client.model.scene.*;
import com.zhongshu.card.client.type.DataState;
import com.zhongshu.card.server.core.dao.scene.SceneComponentDao;
import com.zhongshu.card.server.core.dao.scene.SceneInfoDao;
import com.zhongshu.card.server.core.domain.scene.SceneComponent;
import com.zhongshu.card.server.core.domain.scene.SceneInfo;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.util.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author TRX
 * @date 2024/11/22
 */
@Slf4j
@Service
public class SceneInfoService extends SuperService {

    @Autowired
    private SceneInfoDao sceneInfoDao;

    @Autowired
    private RoleSceneInfoService roleSceneInfoService;

    @Autowired
    private ProjectSceneInfoService projectSceneInfoService;

    @Autowired
    private SceneComponentDao sceneComponentDao;

    public ResultContent saveInfo(SceneInfoParam param) {
        boolean isAdd = true;
        SceneInfo entity = null;

        SceneInfo temp = sceneInfoDao.findTopByName(param.getName());
//        SceneInfo codeTemp = sceneInfoDao.findTopByCode(param.getCode());
        if (StringUtils.isNotEmpty(param.getId())) {
            entity = sceneInfoDao.findTopById(param.getId());
            if (ObjectUtils.isEmpty(entity)) {
                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
            }
            if (ObjectUtils.isNotEmpty(temp) && !temp.getId().equals(entity.getId())) {
                return ResultContent.buildFail(String.format("名称已存在：%s", param.getName()));
            }
//            if (ObjectUtils.isNotEmpty(codeTemp) && !codeTemp.getId().equals(entity.getId())) {
//                return ResultContent.buildFail(String.format("code已存在：%s", param.getName()));
//            }
            initUpdateEntity(entity);
            isAdd = false;
        } else {
            if (ObjectUtils.isNotEmpty(temp)) {
                return ResultContent.buildFail(String.format("名称已存在：%s", param.getName()));
            }
//            if (ObjectUtils.isNotEmpty(codeTemp)) {
//                return ResultContent.buildFail(String.format("code已存在：%s", param.getName()));
//            }
            entity = new SceneInfo();
            initEntityNoCheckOid(entity);
        }
        BeanUtils.copyPropertiesWithoutNull(param, entity);
        sceneInfoDao.save(entity);

        // 编辑关联的信息
        if (!isAdd) {
            projectSceneInfoService.updateAllSceneInfo(entity);
        }

        // 保存场景包含的组件
        saveComponents(entity, param.getComponents());
        return ResultContent.buildSuccess();
    }

    public ResultContent<Page<SceneInfoModel>> page(SceneInfoSearch param, Pageable pageable) {
        Page<SceneInfo> page = sceneInfoDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    public ResultContent<SceneInfoAboutComModel> getDetailById(String id) {
        SceneInfo entity = sceneInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        return ResultContent.buildSuccess(toAboutComModel(entity));
    }

    public ResultContent deleteById(String id) {
        SceneInfo entity = sceneInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        // 判断是否可以删除
        sceneInfoDao.delete(entity);

        // 删除关联的信息
        projectSceneInfoService.deleteBySceneInfoId(entity.getId());
        roleSceneInfoService.deleteBySceneInfoId(entity.getId());
        return ResultContent.buildSuccess();
    }

    @Transactional
    public ResultContent changeState(String id, DataState state) {
        SceneInfo entity = sceneInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        entity.setState(state);
        sceneInfoDao.save(entity);

        // 改变项目已绑定的场景状态
        projectSceneInfoService.changeStateBySceneInfoId(entity.getId(), state);
        return ResultContent.buildSuccess();
    }

    //--------------------------场景组件信息 start---------------------

    public ResultContent deleteComponentById(String id) {
        SceneComponent entity = sceneComponentDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        // 判断是否可以删除
        sceneComponentDao.delete(entity);
        return ResultContent.buildSuccess();
    }

    public ResultContent saveComponents(SceneInfo sceneInfo, List<SceneComponentParam> components) {
        if (ObjectUtils.isNotEmpty(sceneInfo)) {
            List<SceneComponent> oldComponents = sceneComponentDao.findBySceneInfoIdOrderBySortAsc(sceneInfo.getId());
            List<String> ids = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(oldComponents)) {
                ids = oldComponents.stream().map(it -> it.getId()).collect(Collectors.toList());
            }
            if (ObjectUtils.isNotEmpty(components)) {
                List<SceneComponent> componentEntitys = new ArrayList<>();
                for (SceneComponentParam param : components) {
                    SceneComponent component = new SceneComponent();
                    BeanUtils.copyProperties(param, component);
                    componentEntitys.add(component);
                    if (StringUtils.isNotEmpty(param.getId()) && ids.contains(param.getId())) {
                        ids.remove(param.getId());
                    }
                }
                sceneComponentDao.saveAll(componentEntitys);
            }
            // 删除不存在的
            if (ObjectUtils.isNotEmpty(ids)) {
                sceneComponentDao.deleteByIdIn(ids);
            }
        }
        return ResultContent.buildSuccess();
    }

    public List<SceneComponentModel> getSceneAllComponents(String sceneInfoId) {
        List<SceneComponentModel> models = new ArrayList<>();
        if (StringUtils.isNotEmpty(sceneInfoId)) {
            List<SceneComponent> components = sceneComponentDao.findBySceneInfoIdOrderBySortAsc(sceneInfoId);
            if (ObjectUtils.isNotEmpty(components)) {
                models = components.stream().map(this::toComponentModel).collect(Collectors.toUnmodifiableList());
            }
        }
        return models;
    }

    //--------------------------场景组件信息 end-----------------------

    public SceneInfoModel toModel(SceneInfo entity) {
        SceneInfoModel model = new SceneInfoModel();
        if (ObjectUtils.isNotEmpty(entity)) {
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

    public SceneInfoAboutComModel toAboutComModel(SceneInfo entity) {
        SceneInfoAboutComModel model = new SceneInfoAboutComModel();
        if (ObjectUtils.isNotEmpty(entity)) {
            BeanUtils.copyProperties(entity, model);
            // 场景包含的组件
            model.setComponents(getSceneAllComponents(entity.getId()));
        }
        return model;
    }

    public SceneComponentModel toComponentModel(SceneComponent entity) {
        SceneComponentModel model = new SceneComponentModel();
        if (ObjectUtils.isNotEmpty(entity)) {
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

}
