package cn.skcks.docking.gb28181.wvp.service.device;

import cn.skcks.docking.gb28181.common.json.JsonException;
import cn.skcks.docking.gb28181.wvp.orm.mybatis.dynamic.mapper.WvpProxyDeviceDynamicSqlSupport;
import cn.skcks.docking.gb28181.wvp.orm.mybatis.dynamic.mapper.WvpProxyDeviceMapper;
import cn.skcks.docking.gb28181.wvp.orm.mybatis.dynamic.model.WvpProxyDevice;
import com.github.pagehelper.ISelect;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;

@Slf4j
@RequiredArgsConstructor
@Service
public class DeviceService {
    private final WvpProxyDeviceMapper deviceMapper;

    public Optional<WvpProxyDevice> getDeviceById(Long id){
        return deviceMapper.selectOne(s->
                s.where(WvpProxyDeviceDynamicSqlSupport.id, isEqualTo(id)));
    }

    public Optional<WvpProxyDevice> getDeviceByDeviceCode(String deviceCode){
        return deviceMapper.selectOne(s->s.where(WvpProxyDeviceDynamicSqlSupport.deviceCode,isEqualTo(deviceCode)).limit(1));
    }

    public List<WvpProxyDevice> getDeviceByGbDeviceId(String gbDeviceId){
        return deviceMapper.select(s->
                s.where(WvpProxyDeviceDynamicSqlSupport.gbDeviceId,isEqualTo(gbDeviceId)));
    }

    public Optional<WvpProxyDevice> getDeviceByGbDeviceIdAndChannel(String gbDeviceId,String channel){
        return deviceMapper.selectOne(s->
                s.where(WvpProxyDeviceDynamicSqlSupport.gbDeviceId,isEqualTo(gbDeviceId))
                        .and(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId,isEqualTo(channel)).limit(1));
    }

    @Transactional
    public boolean autoUpdateDeviceByGbDeviceIdAndChannel(String gbDeviceId, String channel){
        List<WvpProxyDevice> deviceByGbDeviceId = getDeviceByGbDeviceId(gbDeviceId);
        if(deviceByGbDeviceId.isEmpty()){
            WvpProxyDevice device = new WvpProxyDevice();
            device.setDeviceCode("");
            device.setGbDeviceId(gbDeviceId);
            device.setGbDeviceChannelId(channel);
            return deviceMapper.insert(device) > 0;
        }

        Optional<WvpProxyDevice> deviceByGbDeviceIdAndChannel = getDeviceByGbDeviceIdAndChannel(gbDeviceId,channel);
        if(deviceByGbDeviceIdAndChannel.isPresent()) {
            return deviceMapper.update(u->
                    u.set(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId).equalTo(channel)
                            .where(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId, isEqualTo(gbDeviceId))
                            .and(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId, isEqualTo(channel))) > 0;
        } else {
            WvpProxyDevice device = new WvpProxyDevice();
            device.setDeviceCode("");
            device.setGbDeviceId(gbDeviceId);
            device.setGbDeviceChannelId(channel);
            return deviceMapper.insert(device) > 0;
        }
    }

    /**
     * 添加设备
     * @param device 设备
     * @return 是否成功
     */
    @SneakyThrows
    public boolean addDevice(WvpProxyDevice device) {
        if(device == null){
            return false;
        }

        String deviceCode = device.getDeviceCode();
        if(StringUtils.isBlank(deviceCode)){
            throw new JsonException("设备编码不能为空");
        }
        if(getDeviceByDeviceCode(deviceCode).isPresent()){
            throw new JsonException(MessageFormat.format("设备编码 {0} 已存在" ,deviceCode));
        }

        String gbDeviceId = device.getGbDeviceId();
        String channel = device.getGbDeviceChannelId();
        if(StringUtils.isBlank(gbDeviceId)){
            throw new JsonException("国标编码不能为空");
        }
        if(StringUtils.isBlank(channel)){
            throw new JsonException("国标通道不能为空");
        }
        if(getDeviceByGbDeviceIdAndChannel(gbDeviceId,channel).isPresent()){
            throw new JsonException(MessageFormat.format("国标编码 {0}, 通道 {1} 已存在" ,gbDeviceId, channel));
        }

        return deviceMapper.insert(device) > 0;
    }

    public boolean deleteDeviceByGbDeviceIdAndChannel(String gbDeviceId, String channel){
        return deviceMapper.delete(d->
                d.where(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId, isEqualTo(gbDeviceId))
                .and(WvpProxyDeviceDynamicSqlSupport.gbDeviceChannelId, isEqualTo(channel))) > 0;
    }

    /**
     * 依据 id 或 deviceCode 或  gbDeviceId 删除设备信息
     * @param device 设备
     * @return 是否成功
     */
    public boolean deleteDevice(WvpProxyDevice device){
        if(device == null){
            return false;
        }

        Long id = device.getId();
        String deviceCode = device.getDeviceCode();
        String gbDeviceId = device.getGbDeviceId();
        if(id != null){
            return deviceMapper.deleteByPrimaryKey(id) > 0;
        } else if(StringUtils.isNotBlank(deviceCode)){
            return deviceMapper.delete(d->d.where(WvpProxyDeviceDynamicSqlSupport.deviceCode,isEqualTo(deviceCode))) > 0;
        } else if(StringUtils.isNotBlank(gbDeviceId)){
            return deviceMapper.delete(d->d.where(WvpProxyDeviceDynamicSqlSupport.gbDeviceId,isEqualTo(gbDeviceId))) > 0;
        } else {
            return false;
        }
    }

    /**
     * 分页查询设备
     * @param page 页数
     * @param size 数量
     * @return 分页设备
     */
    public PageInfo<WvpProxyDevice> getDevicesWithPage(int page, int size){
        ISelect select = () -> deviceMapper.select(u -> u.orderBy(WvpProxyDeviceDynamicSqlSupport.id.descending()));
        return getDevicesWithPage(page,size, select);
    }

    /**
     * 分页查询设备
     * @param page 页数
     * @param size 数量
     * @param select 查询语句
     * @return 分页设备
     */
    public PageInfo<WvpProxyDevice> getDevicesWithPage(int page, int size, ISelect select){
        PageInfo<WvpProxyDevice> pageInfo;
        try (Page<WvpProxyDevice> startPage = PageHelper.startPage(page, size)) {
            pageInfo = startPage.doSelectPageInfo(select);
        }
        return pageInfo;
    }

    @SneakyThrows
    public boolean modifyDevice(WvpProxyDevice device){
        if(device == null){
            return false;
        }
        Long id = device.getId();
        if(id == null){
            throw new JsonException("id 不能为空");
        }

        String deviceCode = device.getDeviceCode();
        if(StringUtils.isNotBlank(deviceCode)){
            WvpProxyDevice existDevice = getDeviceByDeviceCode(deviceCode).orElse(null);
            if(existDevice != null && !Objects.equals(existDevice.getId(), device.getId())){
                throw new JsonException(MessageFormat.format("设备编码 {0} 已存在", deviceCode));
            }
        }

        String gbDeviceId = device.getGbDeviceId();
        String gbDeviceChannelId = device.getGbDeviceChannelId();
        if(gbDeviceId != null && StringUtils.isBlank(gbDeviceId)){
            throw new JsonException("国标id 不能为空");
        }
        if(gbDeviceChannelId != null && StringUtils.isBlank(gbDeviceChannelId)){
            throw new JsonException("通道 不能为空");
        }
        if(StringUtils.isNotBlank(gbDeviceId) && StringUtils.isNotBlank(gbDeviceChannelId)){
            WvpProxyDevice existDevice = getDeviceByGbDeviceIdAndChannel(gbDeviceId, gbDeviceChannelId).orElse(null);
            if(existDevice != null && !Objects.equals(existDevice.getId(), device.getId())){
                throw new JsonException(MessageFormat.format("国标id {0} ,通道 {1} 已存在", gbDeviceId, gbDeviceChannelId));
            }
        }
        return deviceMapper.updateByPrimaryKeySelective(device) > 0;
    }
}
