package com.zhongshu.card.server.core.service.devices.permiss;

import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.models.type.DeviceType;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.zhongshu.card.client.model.devices.permiss.*;
import com.zhongshu.card.client.type.DataState;
import com.zhongshu.card.client.type.device.PermissSettingDeviceType;
import com.zhongshu.card.client.type.device.PermissSettingType;
import com.zhongshu.card.server.core.dao.devices.DeviceGroupDao;
import com.zhongshu.card.server.core.dao.devices.PermissSettingDao;
import com.zhongshu.card.server.core.dao.devices.PermissSettingListDao;
import com.zhongshu.card.server.core.dao.devices.PermissTimeSlotDao;
import com.zhongshu.card.server.core.dao.org.OrganizationDao;
import com.zhongshu.card.server.core.dao.org.RoleDao;
import com.zhongshu.card.server.core.dao.org.UserGroupDao;
import com.zhongshu.card.server.core.dao.school.AreaDao;
import com.zhongshu.card.server.core.domain.devices.DeviceGroup;
import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
import com.zhongshu.card.server.core.domain.devices.permiss.PermissSetting;
import com.zhongshu.card.server.core.domain.devices.permiss.PermissSettingList;
import com.zhongshu.card.server.core.domain.devices.permiss.PermissTimeSlot;
import com.zhongshu.card.server.core.domain.org.Organization;
import com.zhongshu.card.server.core.domain.org.Role;
import com.zhongshu.card.server.core.domain.org.UserGroup;
import com.zhongshu.card.server.core.domain.school.Area;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
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.util.Assert;

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

/**
 * 设备权限规则服务
 *
 * @author TRX
 * @date 2024/12/19
 */
@Slf4j
@Service
public class PermissSettingService extends SuperService {

    @Autowired
    private PermissTimeSlotDao permissTimeSlotDao;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private PermissSettingDao permissSettingDao;

    @Autowired
    private PermissTimeSlotService permissTimeSlotService;

    @Autowired
    private DeviceInfoServiceImpl deviceInfoService;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private AreaDao areaDao;

    @Autowired
    private UserGroupDao userGroupDao;

    @Autowired
    private DeviceGroupDao deviceGroupDao;

    @Autowired
    private PermissSettingListDao permissSettingListDao;

    /**
     * 保存设备权限规则数据
     *
     * @param param
     * @return
     */
    public ResultContent saveInfo(PermissSettingParam param) {
        Assert.hasText(param.getProjectOid(), "projectOid不能为空");
        if (StringUtils.isEmpty(param.getTimeSlotId())) {
            return ResultContent.buildFail("所属时段不能为空");
        }
        PermissTimeSlot timeSlot = permissTimeSlotDao.findTopById(param.getTimeSlotId());
        if (ObjectUtils.isEmpty(timeSlot)) {
            return ResultContent.buildFail("所属时段不存在");
        }

        PermissTimeSlot oldtimeSlot = null;
        PermissSetting entity = null;
        PermissSetting nameTemp = permissSettingDao.findTopByNameAndProjectOid(param.getName(), param.getProjectOid());
        if (StringUtils.isNotEmpty(param.getId())) {
            entity = permissSettingDao.findTopById(param.getId());
            if (ObjectUtils.isEmpty(entity)) {
                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
            }
            if (ObjectUtils.isNotEmpty(nameTemp) && !nameTemp.getId().equals(entity.getId())) {
                return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIST, param.getName()));
            }
            initUpdateEntity(entity);
            oldtimeSlot = entity.getTimeSlot();
        } else {
            if (ObjectUtils.isNotEmpty(nameTemp)) {
                return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIST, param.getName()));
            }
            entity = new PermissSetting();
            if (param.getState() == null) {
                param.setState(DataState.Enable);
            }
            initEntityNoCheckOid(entity);
        }
        BeanUtils.copyProperties(param, entity);

        // 规则所属时段
        entity.setTimeSlot(timeSlot);
        entity.setTimeSlotId(timeSlot.getId());
        permissSettingDao.save(entity);

        // 保存规则相关的配置信息
        saveSettingList(entity, param.getList());
        permissTimeSlotService.updateTimeSlotAboutPermiss(timeSlot);
        if (ObjectUtils.isNotEmpty(oldtimeSlot) && !oldtimeSlot.getId().equals(entity.getId())) {
            permissTimeSlotService.updateTimeSlotAboutPermiss(oldtimeSlot);
        }
        return ResultContent.buildSuccess();
    }

    private void saveSettingList(PermissSetting entity, List<PermissSettingConfigParam> list) {
        List<PermissSettingList> olds = permissSettingListDao.findByPermissSettingOrderBySortAsc(entity);
        List<String> ids = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(olds)) {
            ids = olds.stream().map(it -> it.getId()).collect(Collectors.toList());
        }
        if (ObjectUtils.isNotEmpty(list)) {
            List<PermissSettingList> saveList = new ArrayList<>();
            long i = 1;
            for (PermissSettingConfigParam param : list) {
                PermissSettingList permissSettingList = new PermissSettingList();
                if (StringUtils.isNotEmpty(param.getId())) {
                    PermissSettingList temp = permissSettingListDao.findTopById(param.getId());
                    if (ObjectUtils.isEmpty(temp)) {
                        param.setId(null);
                        initEntityNoCheckOid(permissSettingList);
                    } else {
                        permissSettingList = temp;
                        initUpdateEntity(permissSettingList);
                    }
                }
                BeanUtils.copyProperties(param, permissSettingList);
                permissSettingList.setProjectOid(entity.getProjectOid());
                permissSettingList.setPermissSetting(entity);
                permissSettingList.setPermissSettingId(entity.getId());

                permissSettingList.setSort(i);
                saveList.add(permissSettingList);
                if (StringUtils.isNotEmpty(permissSettingList.getId()) && ids.contains(permissSettingList.getId())) {
                    ids.remove(permissSettingList.getId());
                }
                i++;
            }
            permissSettingListDao.saveAll(saveList);
        }
        if (ObjectUtils.isNotEmpty(ids)) {
            permissSettingListDao.deleteAllById(ids);
        }
    }

    public ResultContent<Page<PermissSettingModel>> page(PermissSettingSearch param, Pageable pageable) {
        String projectOid = param.getProjectOid();
        Organization organization = organizationDao.findTopByOid(projectOid);
        if (ObjectUtils.isEmpty(organization)) {
            return ResultContent.buildFail("projectOid不存在");
        }
        Page<PermissSetting> page = permissSettingDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    public ResultContent deleteInfo(String id) {
        PermissSetting entity = permissSettingDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        permissSettingDao.delete(entity);
        permissSettingListDao.deleteByPermissSetting(entity);

        // 更新时段包含的规则
        permissTimeSlotService.updateTimeSlotAboutPermiss(entity.getTimeSlot());
        return ResultContent.buildSuccess();
    }

    public ResultContent<PermissSettingModel> getDetailInfo(String id) {
        PermissSetting entity = permissSettingDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        return ResultContent.buildSuccess(toModel(entity));
    }

    public ResultContent changeState(String id, DataState state) {
        PermissSetting entity = permissSettingDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        entity.setState(state);
        permissSettingDao.save(entity);
        return ResultContent.buildSuccess();
    }

    private PermissSettingModel toModel(PermissSetting entity) {
        PermissSettingModel model = new PermissSettingModel();
        if (ObjectUtils.isNotEmpty(entity)) {
            BeanUtils.copyProperties(entity, model, "list");
            model.setTimeSlot(permissTimeSlotService.toSimpleModel(entity.getTimeSlot()));

            List<PermissSettingList> permissSettingLists = permissSettingListDao.findByPermissSettingOrderBySortAsc(entity);
            // 配置列表
            if (ObjectUtils.isNotEmpty(permissSettingLists)) {
                model.setList(permissSettingLists.stream().map(this::toConfigModel).toList());
            }
        }
        return model;
    }

    /**
     * 人员 - 设备关联模型转换
     *
     * @param param
     * @return
     */
    private PermissSettingConfigModel toConfigModel(PermissSettingList param) {
        PermissSettingConfigModel model = new PermissSettingConfigModel();
        if (ObjectUtils.isNotEmpty(param)) {
            BeanUtils.copyProperties(param, model);

            String deviceNames = "";

            if (ObjectUtils.isNotEmpty(param.getDeviceIds())) {
                List<String> names = new ArrayList<>();
                if (param.getPermissSettingDeviceType() == PermissSettingDeviceType.Device) {
                    // 设备信息
                    List<DeviceInfo> deviceInfos = deviceInfoService.getDevicesByDeviceIds(param.getDeviceIds());
                    if (ObjectUtils.isNotEmpty(deviceInfos)) {
                        names = deviceInfos.stream().map(it -> it.getDeviceName()).toList();
                    }
                } else if (param.getPermissSettingDeviceType() == PermissSettingDeviceType.DeviceGroup) {
                    List<DeviceGroup> list = deviceGroupDao.findByIdIn(param.getDeviceIds());
                    if (ObjectUtils.isNotEmpty(list)) {
                        names = list.stream().map(it -> it.getName()).toList();
                    }
                } else if (param.getPermissSettingDeviceType() == PermissSettingDeviceType.Area) {
                    List<Area> areas = areaDao.findByIdIn(param.getDeviceIds());
                    if (ObjectUtils.isNotEmpty(areas)) {
                        names = areas.stream().map(it -> it.getName()).toList();
                    }
                } else if (param.getPermissSettingDeviceType() == PermissSettingDeviceType.DeviceType) {
                    List<DeviceType> deviceTypes = param.getDeviceTypes();
                    if (ObjectUtils.isNotEmpty(deviceTypes)) {
                        names = deviceTypes.stream().map(it -> it.getRemark()).collect(Collectors.toList());
                    }
                }
                if (ObjectUtils.isNotEmpty(names)) {
                    deviceNames = StringUtils.join(names, ",");
                }
            }
            model.setDeviceNames(deviceNames);

            String aboutShowDataName = "";
            // 关联的数据名称
            if (param.getPermissSettingType() == PermissSettingType.Sex) {
                List<String> names = new ArrayList<>();
                // 性别
                if (param.getSex() != null) {
                    names = param.getSex().stream().map(it -> it.getRemark()).collect(Collectors.toList());
                }
                aboutShowDataName = StringUtils.join(names, ",");
            } else {
                if (ObjectUtils.isNotEmpty(param.getDataIds())) {
                    List<String> names = new ArrayList<>();
                    if (param.getPermissSettingType() == PermissSettingType.Role) {
                        // 角色
                        List<Role> roles = roleDao.findByIdIn(param.getDataIds());
                        if (ObjectUtils.isNotEmpty(roles)) {
                            names = roles.stream().map(it -> it.getName()).toList();
                        }
                    } else if (param.getPermissSettingType() == PermissSettingType.Org) {
                        // 机构
                        List<Organization> orgs = organizationDao.findByOidIn(param.getDataIds());
                        if (ObjectUtils.isNotEmpty(orgs)) {
                            names = orgs.stream().map(it -> it.getName()).toList();
                        }
                    } else if (param.getPermissSettingType() == PermissSettingType.Area) {
                        // 区域
                        List<Area> areas = areaDao.findByIdIn(param.getDataIds());
                        if (ObjectUtils.isNotEmpty(areas)) {
                            names = areas.stream().map(it -> it.getName()).toList();
                        }
                    } else if (param.getPermissSettingType() == PermissSettingType.UserGroup) {
                        // 用户分组
                        List<UserGroup> userGroups = userGroupDao.findByIdIn(param.getDataIds());
                        if (ObjectUtils.isNotEmpty(userGroups)) {
                            names = userGroups.stream().map(it -> it.getName()).toList();
                        }
                    }

                    if (ObjectUtils.isNotEmpty(names)) {
                        aboutShowDataName = String.join(",", names);
                    }
                }
            }
            model.setAboutShowDataName(aboutShowDataName);
        }
        return model;
    }
}
