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

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.auth.OpenInterfaceAuthDeviceDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.auth.OpenInterfaceAuthDeviceImportDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.auth.OpenInterfaceAuthDevicePageDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.auth.OpenInterfaceAuthDeviceVo;
import cn.hanghui.outapi.platform.tenant.entity.po.ApplicationType;
import cn.hanghui.outapi.platform.tenant.entity.po.DeviceModel;
import cn.hanghui.outapi.platform.tenant.entity.po.OpenInterfaceAuthDevice;
import cn.hanghui.outapi.platform.tenant.entity.po.Purchaser;
import cn.hanghui.outapi.platform.tenant.mapper.ApplicationTypeMapper;
import cn.hanghui.outapi.platform.tenant.mapper.DeviceModelMapper;
import cn.hanghui.outapi.platform.tenant.mapper.OpenInterfaceAuthDeviceMapper;
import cn.hanghui.outapi.platform.tenant.mapper.PurchaserMapper;
import cn.hanghui.outapi.platform.tenant.service.OpenInterfaceAuthDeviceService;
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.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shisl
 * @package cn.hanghui.outapi.platform.tenant.service.impl
 * @class OpenInterfaceAuthDeviceServiceImpl
 * @date 2024/1/17 下午3:45
 * @description
 */
@Service
@Slf4j
public class OpenInterfaceAuthDeviceServiceImpl implements OpenInterfaceAuthDeviceService {

    @Resource
    private OpenInterfaceAuthDeviceMapper openInterfaceAuthDeviceMapper;
    @Resource
    private ApplicationTypeMapper applicationTypeMapper;
    @Resource
    private DeviceModelMapper deviceModelMapper;
    @Resource
    private PurchaserMapper purchaserMapper;


    @Override
    public RestResult<Boolean> add(OpenInterfaceAuthDeviceDto dto) {
        OpenInterfaceAuthDevice authDevice = null;
        if (Preconditions.isNotBlank(dto.getId())) {
            authDevice = openInterfaceAuthDeviceMapper.selectById(dto.getId());
            if (Preconditions.isBlank(authDevice)) {
                return RestResult.error("数据不存在或已删除");
            }
            authDevice.setApplicationTypeId(dto.getApplicationTypeId());
            authDevice.setDeviceModelId(dto.getDeviceModelId());
            authDevice.setPurchaserId(dto.getPurchaserId());
            authDevice.setUpdateTime(new Date());
            openInterfaceAuthDeviceMapper.updateById(authDevice);

        } else {
            authDevice = openInterfaceAuthDeviceMapper.selectOne(Wrappers.lambdaQuery(OpenInterfaceAuthDevice.class).eq(OpenInterfaceAuthDevice::getSn, dto.getSn()));
            if (Preconditions.isNotBlank(authDevice)) {
                return RestResult.error("设备已授权，勿重复授权");
            }
            authDevice = BeanUtil.copyProperties(dto, OpenInterfaceAuthDevice.class);
            authDevice.setStatus(Boolean.TRUE);
            authDevice.setCreateTime(new Date());
            authDevice.setIsDeleted(Boolean.FALSE);
            authDevice.setVersion(0);
            openInterfaceAuthDeviceMapper.insert(authDevice);
        }
        return RestResult.ok(Boolean.TRUE);
    }

    @Override
    public RestResult<Boolean> batchAdd(OpenInterfaceAuthDeviceImportDto dto) {
        ApplicationType applicationType = applicationTypeMapper.selectOne(Wrappers.lambdaQuery(ApplicationType.class).eq(ApplicationType::getApplicationType, dto.getApplicationType()));
        if (Preconditions.isBlank(applicationType)) {
            return RestResult.error("应用类型不存在");
        }

        DeviceModel deviceModel = deviceModelMapper.selectOne(Wrappers.lambdaQuery(DeviceModel.class).eq(DeviceModel::getDeviceModel, dto.getDeviceModel()));
        if (Preconditions.isBlank(deviceModel)) {
            return RestResult.error("设备类型不存在");
        }

        Purchaser purchaser = purchaserMapper.selectOne(Wrappers.lambdaQuery(Purchaser.class).eq(Purchaser::getCompanyName, dto.getPurchaserName()));
        if (Preconditions.isBlank(purchaser)) {
            return RestResult.error("购买方不存在");
        }

        OpenInterfaceAuthDevice deviceAuth = openInterfaceAuthDeviceMapper.selectOne(Wrappers.lambdaQuery(OpenInterfaceAuthDevice.class).eq(OpenInterfaceAuthDevice::getSn, dto.getSn()));
        if (Preconditions.isNotBlank(deviceAuth)) {
            return RestResult.error("设备已授权，勿重复授权");
        }

        OpenInterfaceAuthDevice device = new OpenInterfaceAuthDevice();
        device.setSn(dto.getSn());
        device.setStatus(Boolean.TRUE);
        device.setPurchaserId(purchaser.getId());
        device.setDeviceModelId(deviceModel.getId());
        device.setApplicationTypeId(applicationType.getId());
        device.setCreateTime(new Date());
        device.setUpdateTime(new Date());
        device.setIsDeleted(Boolean.FALSE);
        device.setVersion(0);
        openInterfaceAuthDeviceMapper.insert(device);
        return RestResult.ok(Boolean.TRUE);
    }

    @Override
    public RestResult<Boolean> del(Long id) {
        OpenInterfaceAuthDevice authDevice = openInterfaceAuthDeviceMapper.selectById(id);
        if (Preconditions.isBlank(authDevice)) {
            return RestResult.error("数据不存在或已删除");
        }
        openInterfaceAuthDeviceMapper.deleteById(authDevice);
        return RestResult.ok(Boolean.TRUE);
    }

    @Override
    public RestResult<Boolean> updateStatus(Long id, Boolean status) {
        OpenInterfaceAuthDevice authDevice = openInterfaceAuthDeviceMapper.selectById(id);
        if (Preconditions.isBlank(authDevice)) {
            return RestResult.error("数据不存在或已删除");
        }
        authDevice.setStatus(status);
        authDevice.setUpdateTime(new Date());
        openInterfaceAuthDeviceMapper.updateById(authDevice);
        return RestResult.ok(Boolean.TRUE);
    }

    @Override
    public RestResult<IPage<OpenInterfaceAuthDeviceVo>> page(OpenInterfaceAuthDevicePageDto dto) {
        Page<OpenInterfaceAuthDevice> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<OpenInterfaceAuthDevice> wrapper = new LambdaQueryWrapper<>();
        if (Preconditions.isNotBlank(dto.getPurchaserId())) {
            wrapper.eq(OpenInterfaceAuthDevice::getPurchaserId, dto.getPurchaserId());
        }
        if (Preconditions.isNotBlank(dto.getApplicationTypeId())) {
            wrapper.eq(OpenInterfaceAuthDevice::getApplicationTypeId, dto.getApplicationTypeId());
        }
        if (Preconditions.isNotBlank(dto.getDeviceModelId())) {
            wrapper.eq(OpenInterfaceAuthDevice::getDeviceModelId, dto.getDeviceModelId());
        }
        if (Preconditions.isNotBlank(dto.getStatus())) {
            wrapper.eq(OpenInterfaceAuthDevice::getStatus, dto.getStatus());
        }
        if (Preconditions.isNotBlank(dto.getSn())) {
            wrapper.like(OpenInterfaceAuthDevice::getSn, dto.getSn());
        }
        wrapper.orderByDesc(OpenInterfaceAuthDevice::getId);
        IPage<OpenInterfaceAuthDevice> iPage = openInterfaceAuthDeviceMapper.selectPage(page, wrapper);
        IPage<OpenInterfaceAuthDeviceVo> convert = iPage.convert(t -> {
            OpenInterfaceAuthDeviceVo item = BeanUtil.copyProperties(t, OpenInterfaceAuthDeviceVo.class);
            return item;
        });
        complete(convert);
        return RestResult.ok(convert);
    }

    private void complete(IPage<OpenInterfaceAuthDeviceVo> convert) {
        List<OpenInterfaceAuthDeviceVo> records = convert.getRecords();
        if (Preconditions.isBlank(records)) {
            return;
        }
        Map<Long, ApplicationType> applicationTypeMap = null;
        Map<Long, Purchaser> purchaserMap = null;
        Map<Long, DeviceModel> deviceModelMap = null;
        List<Long> applicationIds = records.stream().map(OpenInterfaceAuthDeviceVo::getApplicationTypeId).collect(Collectors.toList());
        List<Long> purchaserIds = records.stream().map(OpenInterfaceAuthDeviceVo::getPurchaserId).collect(Collectors.toList());
        List<Long> deviceModelIds = records.stream().map(OpenInterfaceAuthDeviceVo::getDeviceModelId).collect(Collectors.toList());
        List<ApplicationType> applicationTypes = applicationTypeMapper.selectList(Wrappers.lambdaQuery(ApplicationType.class).in(ApplicationType::getId, applicationIds));
        if (Preconditions.isNotBlank(applicationTypes)) {
            applicationTypeMap = applicationTypes.stream().collect(Collectors.toMap(ApplicationType::getId, a -> a, (k1, k2) -> k1));
        }

        List<DeviceModel> deviceModels = deviceModelMapper.selectList(Wrappers.lambdaQuery(DeviceModel.class).in(DeviceModel::getId, deviceModelIds));
        if (Preconditions.isNotBlank(deviceModels)) {
            deviceModelMap = deviceModels.stream().collect(Collectors.toMap(DeviceModel::getId, a -> a, (k1, k2) -> k1));
        }

        List<Purchaser> purchasers = purchaserMapper.selectList(Wrappers.lambdaQuery(Purchaser.class).in(Purchaser::getId, purchaserIds));
        if (Preconditions.isNotBlank(purchasers)) {
            purchaserMap = purchasers.stream().collect(Collectors.toMap(Purchaser::getId, a -> a, (k1, k2) -> k1));
        }
        Map<Long, ApplicationType> finalApplicationTypeMap = applicationTypeMap;
        Map<Long, DeviceModel> finalDeviceModelMap = deviceModelMap;
        Map<Long, Purchaser> finalPurchaserMap = purchaserMap;
        records.stream().forEach(item -> {
            if (Preconditions.isNotBlank(finalApplicationTypeMap) && finalApplicationTypeMap.containsKey(item.getApplicationTypeId())) {
                item.setApplicationType(finalApplicationTypeMap.get(item.getApplicationTypeId()).getApplicationType());
            }
            if (Preconditions.isNotBlank(finalDeviceModelMap) && finalDeviceModelMap.containsKey(item.getDeviceModelId())) {
                item.setDeviceModel(finalDeviceModelMap.get(item.getDeviceModelId()).getDeviceModel());
            }
            if (Preconditions.isNotBlank(finalPurchaserMap) && finalPurchaserMap.containsKey(item.getPurchaserId())) {
                item.setPurchaserName(finalPurchaserMap.get(item.getPurchaserId()).getCompanyName());
            }
        });
        convert.setRecords(records);
    }
}
