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

import cn.hanghui.outapi.platform.common.entity.po.Account;
import cn.hanghui.outapi.platform.common.entity.po.AccountAuthConfig;
import cn.hanghui.outapi.platform.common.entity.rest.RestCode;
import cn.hanghui.outapi.platform.common.mapper.AccountAuthConfigMapper;
import cn.hanghui.outapi.platform.common.utils.ClassUtil;
import cn.hanghui.outapi.platform.common.utils.Preconditions;
import cn.hanghui.outapi.platform.tenant.entity.common.DeviceTemplateCommonParams;
import cn.hanghui.outapi.platform.tenant.entity.config.auth.DeviceConfigBean;
import cn.hanghui.outapi.platform.tenant.entity.enums.AuthModuleTypeEnum;
import cn.hanghui.outapi.platform.tenant.entity.enums.ModuleTypeEnum;
import cn.hanghui.outapi.platform.tenant.entity.enums.SystemTypeEnum;
import cn.hanghui.outapi.platform.tenant.entity.po.*;
import cn.hanghui.outapi.platform.tenant.mapper.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @description:
 * @ClassName CommonImpl
 * @Author WXG
 * @Date 2023/12/28 15:28
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CommonImpl {

    private final PurchaserMapper purchaserMapper;
    private final ApplicationTypeMapper applicationTypeMapper;
    private final DeviceModelMapper deviceModelMapper;
    private final AmpeMapper ampeMapper;
    private final TenantMapper tenantMapper;
    private final UserLibMapper userLibMapper;
    private final SceneMapper sceneMapper;
    private final AccountAuthConfigMapper accountAuthConfigMapper;

    public <T> Map<Long, Purchaser> getPurchaserMap(IPage<T> pageList, Function<T, Long> function) {
        return getPurchaserMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, Purchaser> getPurchaserMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<Purchaser> list = purchaserMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(Purchaser::getId, Function.identity()));
    }

    public <T> Map<Long, ApplicationType> getApplicationTypeMap(IPage<T> pageList, Function<T, Long> function) {
        return getApplicationTypeMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, ApplicationType> getApplicationTypeMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<ApplicationType> list = applicationTypeMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(ApplicationType::getId, Function.identity()));
    }


    public <T> Map<Long, DeviceModel> getDeviceModelMap(IPage<T> pageList, Function<T, Long> function) {
        return getDeviceModelMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, DeviceModel> getDeviceModelMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<DeviceModel> list = deviceModelMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(DeviceModel::getId, Function.identity()));
    }

    public <T> Map<Long, Ampe> getAmpeMap(IPage<T> pageList, Function<T, Long> function) {
        return getAmpeMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, Ampe> getAmpeMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<Ampe> list = ampeMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(Ampe::getId, Function.identity()));
    }

    public <T> Map<Long, Tenant> getTenantMap(IPage<T> pageList, Function<T, Long> function) {
        return getTenantMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, Tenant> getTenantMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<Tenant> list = tenantMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(Tenant::getId, Function.identity()));
    }

    public <T> Map<Long, UserLib> getUserLibMap(IPage<T> pageList, Function<T, Long> function) {
        return getUserLibMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, UserLib> getUserLibMap(List<T> records, Function<T, Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<UserLib> list = userLibMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(UserLib::getId, Function.identity()));
    }

    public <T> Map<Long, Scene> getSceneMap(IPage<T> pageList, Function<T, Long> function) {
        return getSceneMap(pageList.getRecords(), function);
    }

    public <T> Map<Long, Scene> getSceneMap(List<T> records, Function<T, java.lang.Long> function) {
        if (CollUtil.isEmpty(records)) {
            return new HashMap<>();
        }
        List<java.lang.Long> idList = records.stream().map(function).collect(Collectors.toList());
        if (CollUtil.isEmpty(idList)) {
            return new HashMap<>();
        }
        List<cn.hanghui.outapi.platform.tenant.entity.po.Scene> list = sceneMapper.selectBatchIds(idList);
        return list.stream().collect(Collectors.toMap(cn.hanghui.outapi.platform.tenant.entity.po.Scene::getId, Function.identity()));
    }

    /**
     * 校验设备或模版参数是否存在
     *
     * @param params
     */
    public void checkDeviceTemplateCommonParams(DeviceTemplateCommonParams params) {
        //购买方
        if (Preconditions.isNotBlank(params.getPurchaserId())) {
            Purchaser purchaser = purchaserMapper.selectById(params.getPurchaserId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(purchaser), RestCode.FAIL.getCode(), "购买方不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(purchaser.getIsDeleted()), RestCode.FAIL.getCode(), "购买方已删除");
        }
        //应用类型
        if (Preconditions.isNotBlank(params.getApplicationTypeId())) {
            ApplicationType applicationType = applicationTypeMapper.selectById(params.getApplicationTypeId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(applicationType), RestCode.FAIL.getCode(), "应用类型不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(applicationType.getIsDeleted()), RestCode.FAIL.getCode(), "应用类型已删除");
        }
        //设备类型（硬件）
        if (Preconditions.isNotBlank(params.getDeviceModelHardwareId())) {
            DeviceModel deviceModelHardware = deviceModelMapper.selectById(params.getDeviceModelHardwareId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelHardware), RestCode.FAIL.getCode(), "设备类型（硬件）不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelHardware.getIsDeleted()), RestCode.FAIL.getCode(), "设备类型（硬件）已删除");
        }
        //设备类型（环境）
        if (Preconditions.isNotBlank(params.getDeviceModelEnvironmentId())) {
            DeviceModel deviceModelEnvironment = deviceModelMapper.selectById(params.getDeviceModelEnvironmentId());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelEnvironment), RestCode.FAIL.getCode(), "设备类型（环境）不存在");
            ClassUtil.throwBusinessException(ObjectUtil.isNull(deviceModelEnvironment.getIsDeleted()), RestCode.FAIL.getCode(), "设备类型（环境）已删除");
        }
        //系统类型
        if (Preconditions.isNotBlank(params.getSystemTypeCode())) {
            SystemTypeEnum systemTypeEnum = SystemTypeEnum.getEnumByCode(params.getSystemTypeCode());
            ClassUtil.throwBusinessException(ObjectUtil.isNull(systemTypeEnum), RestCode.FAIL.getCode(), "系统类型不存在");
        }
    }

    public List<Long> getAmpeTenantIds(Account account) {
        LambdaQueryWrapper<AccountAuthConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountAuthConfig::getAccountId, account.getId()).eq(AccountAuthConfig::getIsDeleted, Boolean.FALSE);
        AccountAuthConfig config = accountAuthConfigMapper.selectOne(wrapper);
        if (Preconditions.isBlank(config)
                || Preconditions.isBlank(config.getHhAromeSwitch())
                || !config.getHhAromeSwitch()
                || Preconditions.isBlank(config.getDeviceConfig())) {
            return null;
        }
        List<DeviceConfigBean> deviceConfig = config.getDeviceConfig();
        List<DeviceConfigBean> filterTenants = deviceConfig.stream().filter(item -> (ModuleTypeEnum.TENANT.getCode().intValue() == item.getModuleType().intValue() && item.getModuleSwitch() && Preconditions.isNotBlank(item.getModuleValues()))).collect(Collectors.toList());
        if (Preconditions.isBlank(filterTenants)) {
            return null;
        }
        List<Long> tenantIds = new ArrayList<>();
        filterTenants.stream().forEach(item -> {
            tenantIds.addAll(item.getModuleValues().stream()
                    .map(obj -> (obj instanceof Long) ? (Long) obj : Long.parseLong(obj.toString()))
                    .collect(Collectors.toList()));
        });
        if (Preconditions.isBlank(tenantIds)) {
            return null;
        }
        return tenantIds;
    }

    public List<Long> getAuthAmpeIds(Account account) {
        LambdaQueryWrapper<AccountAuthConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountAuthConfig::getAccountId, account.getId()).eq(AccountAuthConfig::getIsDeleted, Boolean.FALSE);
        AccountAuthConfig config = accountAuthConfigMapper.selectOne(wrapper);
        if (Preconditions.isBlank(config)
                || Preconditions.isBlank(config.getHhAromeSwitch())
                || !config.getHhAromeSwitch()
                || Preconditions.isBlank(config.getDeviceConfig())) {
            return null;
        }
        List<DeviceConfigBean> deviceConfig = config.getDeviceConfig();
        List<DeviceConfigBean> filterAmpes = deviceConfig.stream().filter(item -> (ModuleTypeEnum.AMPE.getCode().intValue() == item.getModuleType().intValue() && item.getModuleSwitch() && Preconditions.isNotBlank(item.getModuleValues()))).collect(Collectors.toList());
        if (Preconditions.isBlank(filterAmpes)) {
            return null;
        }
        List<Long> ampeIds = new ArrayList<>();
        filterAmpes.stream().forEach(item -> {
            ampeIds.addAll(item.getModuleValues().stream()
                    .map(obj -> (obj instanceof Long) ? (Long) obj : Long.parseLong(obj.toString()))
                    .collect(Collectors.toList()));
        });
        if (Preconditions.isBlank(ampeIds)) {
            return null;
        }
        return ampeIds;
    }


    public List<Long> getAuthModuleIds(Account account, AuthModuleTypeEnum authModuleTypeEnum) {
        LambdaQueryWrapper<AccountAuthConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountAuthConfig::getAccountId, account.getId()).eq(AccountAuthConfig::getIsDeleted, Boolean.FALSE);
        AccountAuthConfig config = accountAuthConfigMapper.selectOne(wrapper);
        if (Preconditions.isBlank(config)) {
            return null;
        }

        List<Long> moduleIds = new ArrayList<>();
        switch (authModuleTypeEnum) {
            case HHFACE_TENANT:
                moduleIds = config.getHhfaceFaceConfigTenantIds();
                break;
            case HHFACE_USER_LIB:
                moduleIds = config.getHhfaceFaceConfigUserLibIds();
                break;
        }
        return moduleIds;
    }
}
