package com.usky.ems.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.core.util.UUIDUtils;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.ems.domain.DmpDevice;
import com.usky.ems.domain.DmpGateway;
import com.usky.ems.mapper.DmpDeviceMapper;
import com.usky.ems.mapper.DmpGatewayMapper;
import com.usky.ems.service.DmpGatewayService;
import com.usky.ems.service.vo.DmpGatewayDevicePageRequest;
import com.usky.ems.service.vo.DmpGatewayDetailResponse;
import com.usky.ems.service.vo.DmpGatewayListItem;
import com.usky.ems.service.vo.DmpGatewayPageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * dmp_gateway 服务实现
 */
@Service
public class DmpGatewayServiceImpl extends AbstractCrudService<DmpGatewayMapper, DmpGateway> implements DmpGatewayService {

    private final DmpDeviceMapper dmpDeviceMapper;

    public DmpGatewayServiceImpl(DmpDeviceMapper dmpDeviceMapper) {
        this.dmpDeviceMapper = dmpDeviceMapper;
    }

    @Override
    public void add(DmpGateway entity) {
        if (!StringUtils.hasText(entity.getDeviceUuid())) {
            entity.setDeviceUuid(UUIDUtils.uuid().substring(0, 16));
        }

        if (!StringUtils.hasText(entity.getName())) {
            throw new BusinessException("新增失败，名称不能为空");
        }
        if (deviceUuidExists(entity.getDeviceUuid(), null)) {
            throw new BusinessException("新增失败，设备 UUID 已存在");
        }
        LocalDateTime now = LocalDateTime.now();
        if (entity.getCommStatus() == null) {
            entity.setCommStatus(0);
        }
        if (entity.getVirtualDevice() == null) {
            entity.setVirtualDevice(0);
        }
        entity.setCreatedBy(SecurityUtils.getUsername());
        entity.setCreateTime(now);
        entity.setUpdatedBy(SecurityUtils.getUsername());
        entity.setUpdateTime(now);
        entity.setTenantId(SecurityUtils.getTenantId());
        this.save(entity);
    }

    @Override
    public void update(DmpGateway entity) {
        if (entity.getId() == null) {
            throw new BusinessException("修改失败，缺少主键");
        }
        DmpGateway existing = this.getById(entity.getId());
        Optional.ofNullable(existing).orElseThrow(() -> new BusinessException("网关不存在"));

        entity.setUpdatedBy(SecurityUtils.getUsername());
        entity.setUpdateTime(LocalDateTime.now());
        this.updateById(entity);
    }

    @Override
    public boolean remove(Integer id) {
        DmpGateway g = this.getById(id);
        Optional.ofNullable(g).orElseThrow(() -> new BusinessException("网关不存在"));
        return this.removeById(id);
    }

    @Override
    public CommonPage<DmpGatewayListItem> pageGateways(DmpGatewayPageRequest request) {
        int current = request.getCurrent() == null ? 1 : request.getCurrent();
        int size = request.getSize() == null ? 10 : request.getSize();
        Page<DmpGateway> p = new Page<>(current, size);
        LambdaQueryWrapper<DmpGateway> q = Wrappers.lambdaQuery();
        if (request.getCommunicationStatus() != null) {
            q.eq(DmpGateway::getCommStatus, request.getCommunicationStatus());
        }
        if (StringUtils.hasText(request.getName())) {
            q.like(DmpGateway::getName, request.getName());
        }
        if (StringUtils.hasText(request.getInstallAddress())) {
            q.like(DmpGateway::getInstallAddress, request.getInstallAddress());
        }
        if (StringUtils.hasText(request.getDeviceUuid())) {
            q.eq(DmpGateway::getDeviceUuid, request.getDeviceUuid());
        }
        q.orderByDesc(DmpGateway::getId);
        Page<DmpGateway> page = baseMapper.selectPage(p, q);
        List<DmpGatewayListItem> list = page.getRecords().stream().map(this::toListItem).collect(Collectors.toList());
        return new CommonPage<>(list, page.getTotal(), size, current);
    }

    @Override
    public CommonPage<DmpDevice> pageGatewayDevices(DmpGatewayDevicePageRequest request) {
        if (!StringUtils.hasText(request.getGatewayUuid())) {
            throw new BusinessException("查询失败，gatewayUuid 不能为空");
        }
        int current = request.getCurrent() == null ? 1 : request.getCurrent();
        int size = request.getSize() == null ? 10 : request.getSize();
        Page<DmpDevice> p = new Page<>(current, size);
        LambdaQueryWrapper<DmpDevice> q = Wrappers.lambdaQuery();
        q.eq(DmpDevice::getGatewayUuid, request.getGatewayUuid());
        q.eq(DmpDevice::getDeleteFlag, 0);
        q.eq(DmpDevice::getCategoryType, 3);
        Integer tenantId = SecurityUtils.getTenantId();
        if (tenantId != null) {
            q.eq(DmpDevice::getTenantId, tenantId);
        }
        q.orderByDesc(DmpDevice::getId);
        Page<DmpDevice> page = dmpDeviceMapper.selectPage(p, q);
        return new CommonPage<>(page.getRecords(), page.getTotal(), size, current);
    }

    @Override
    public DmpGatewayDetailResponse getGatewayDetail(Integer id) {
        DmpGateway g = this.getById(id);
        if (g == null) {
            return null;
        }
        return toDetail(g);
    }

    private boolean deviceUuidExists(String deviceUuid, Integer excludeId) {
        LambdaQueryWrapper<DmpGateway> w = Wrappers.lambdaQuery();
        w.eq(DmpGateway::getDeviceUuid, deviceUuid);
        DmpGateway one = this.getOne(w);
        if (one == null) {
            return false;
        }
        return excludeId == null || !Objects.equals(one.getId(), excludeId);
    }

    private DmpGatewayListItem toListItem(DmpGateway g) {
        DmpGatewayListItem item = new DmpGatewayListItem();
        item.setId(g.getId());
        item.setDeviceUuid(g.getDeviceUuid());
        item.setName(g.getName());
        item.setIp(g.getIp());
        item.setPort(g.getPort());
        item.setCommunicationStatus(g.getCommStatus());
        item.setInstallAddress(g.getInstallAddress());
        item.setOnlineTime(g.getOnlineTime());
        item.setOfflineTime(g.getOfflineTime());
        item.setVirtualDevice(g.getVirtualDevice());
        item.setCreateTime(g.getCreateTime());
        item.setUpdateTime(g.getUpdateTime());
        return item;
    }

    private DmpGatewayDetailResponse toDetail(DmpGateway g) {
        DmpGatewayDetailResponse r = new DmpGatewayDetailResponse();
        r.setId(g.getId());
        r.setDeviceUuid(g.getDeviceUuid());
        r.setName(g.getName());
        r.setIp(g.getIp());
        r.setPort(g.getPort());
        r.setCommunicationStatus(g.getCommStatus());
        r.setInstallAddress(g.getInstallAddress());
        r.setOnlineTime(g.getOnlineTime());
        r.setOfflineTime(g.getOfflineTime());
        r.setUpdateConfigTime(g.getUpdateConfigTime());
        r.setUpdateProtocolTime(g.getUpdateProtocolTime());
        r.setUpgradeTime(g.getUpgradeTime());
        r.setVirtualDevice(g.getVirtualDevice());
        r.setRemark(g.getRemark());
        r.setUpdatedBy(g.getUpdatedBy());
        r.setUpdateTime(g.getUpdateTime());
        r.setCreatedBy(g.getCreatedBy());
        r.setCreateTime(g.getCreateTime());
        return r;
    }
}
