package com.sunyard.chsm.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sun.jna.Platform;
import com.sunyard.chsm.mapper.SpDeviceMapper;
import com.sunyard.chsm.model.entity.Device;
import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
import com.sunyard.chsm.sdf.adapter.SdfApiAdapterFactory;
import com.sunyard.chsm.sdf.model.DeviceInfo;
import com.sunyard.chsm.sdf.model.EccPubKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author liulu
 * @since 2024/11/4
 */
@Slf4j
@Component
public class DeviceTask implements InitializingBean {

    @Resource
    private SpDeviceMapper spDeviceMapper;

    @Resource
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    private void checkDeviceStatus() {

        for (int i = 1; i < 500; i++) {
            Page<Device> devicePage = spDeviceMapper.selectPage(
                    new Page<>(i, 20L),
                    new LambdaQueryWrapper<Device>().orderByAsc(Device::getId)
            );
            List<Device> records = devicePage.getRecords();
            if (CollectionUtils.isEmpty(records)) {
                break;
            }

            for (Device record : records) {
                boolean connected = false;
                try {
                    SdfApiAdapter sdfApiAdapter = SdfApiAdapterFactory.newInstance(record.getManufacturerModel(), record.getServiceIp(), record.getServicePort());
                    String dh = sdfApiAdapter.openDevice();
                    String sh = sdfApiAdapter.openSession(dh);
                    DeviceInfo info = sdfApiAdapter.getDeviceInfo(sh);
                    log.info("get DeviceInfo: {}", info);
                    EccPubKey eccPubKey = sdfApiAdapter.exportEncPublicKeyECC(sh, 2);
                    log.info("exportEncPublicKeyECC: {}", eccPubKey.getPubKeyHex());
                    sdfApiAdapter.closeSession(sh);
                    sdfApiAdapter.closeDevice(dh);
                    connected = true;

                } catch (Exception ex) {
                    log.warn("设备 {}:{} 连接异常", record.getServiceIp(), record.getServicePort(), ex);
                }
                Device up = new Device();
                up.setId(record.getId());
                up.setConnected(connected);
                LocalDateTime now = LocalDateTime.now();
                if (connected) {
                    up.setLastConnectedTime(now);
                }
                up.setLastCheckTime(now);
                spDeviceMapper.updateById(up);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (Platform.isLinux() || Platform.isWindows()) {
            threadPoolTaskScheduler.scheduleWithFixedDelay(this::checkDeviceStatus, Duration.ofMinutes(5L));
        } else {
            log.warn("操作系统: {} 不支持启动检查设备状态定时任务", System.getProperty("os.name"));
        }

    }
}
