package org.wfc.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wfc.common.core.utils.PageUtils;
import org.wfc.common.core.utils.ResponseUtils;
import org.wfc.common.core.web.page.TableDataInfo;
import org.wfc.common.redis.service.RedisService;
import org.wfc.omada.api.device.OmadaApApi;
import org.wfc.omada.api.device.OmadaDeviceApi;
import org.wfc.omada.api.device.model.AdoptDeviceRequest;
import org.wfc.omada.api.device.model.ApGeneralConfig;
import org.wfc.omada.api.device.model.DeviceInfo;
import org.wfc.omada.api.device.model.DeviceListAddBySnOpenApiVo;
import org.wfc.omada.api.device.model.OperationResponseApGeneralConfig;
import org.wfc.omada.api.device.model.OperationResponseDeviceAddRespOpenApiVo;
import org.wfc.omada.api.device.model.OperationResponseGridVoDeviceInfo;
import org.wfc.omada.api.device.model.OperationResponseWithoutResult;
import org.wfc.omada.api.maintenance.OmadaHistoryDataRetentionApi;
import org.wfc.omada.api.maintenance.model.HistoryRetentionOpenApiVo;
import org.wfc.omada.api.maintenance.model.ModifyHistoryRetentionOpenApiVo;
import org.wfc.omada.api.maintenance.model.OperationResponseHistoryRetentionOpenApiVo;
import org.wfc.omada.api.organization.OmadaSiteApi;
import org.wfc.omada.api.organization.model.OperationResponseGridVoSiteSummaryInfo;
import org.wfc.omada.api.organization.model.SiteSummaryInfo;
import org.wfc.system.domain.SysDevice;
import org.wfc.system.domain.convert.SysDashboardConvert;
import org.wfc.system.mapper.SysDeviceMapper;
import org.wfc.system.service.ISysDeviceService;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 客户平台-设备表 服务实现类
 * </p>
 *
 * @author sys
 * @since 2025-01-07
 */
@Slf4j
@Service
public class SysDeviceServiceImpl extends ServiceImpl<SysDeviceMapper, SysDevice> implements ISysDeviceService {

    @Autowired
    private OmadaSiteApi omadaSiteApi;

    @Autowired
    private OmadaDeviceApi omadaDeviceApi;

    @Autowired
    private OmadaHistoryDataRetentionApi omadaHistoryDataRetentionApi;

    @Autowired
    private OmadaApApi omadaApApi;

    @Autowired
    private RedisService redisService;

    private static final String REDIS_ACCESS_TOKEN = "wfc-api-omada:access-token";
    private static final String REDIS_REFRESH_TOKEN = "wfc-api-omada:refresh-token";
    private static final int OMADA_ERROR_CODE = -44112;
    private static final int OMADA_SUCCESS_CODE = 0;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deviceJob() {
        ResponseEntity<OperationResponseGridVoSiteSummaryInfo> siteList = omadaSiteApi.getSiteList(1, 1000);
        if (siteList.getBody() == null) {
            return false;
        }
        // 更换omada清空redis
        if (siteList.getBody().getErrorCode() == OMADA_ERROR_CODE) {
            redisService.deleteObject(REDIS_ACCESS_TOKEN);
            redisService.deleteObject(REDIS_REFRESH_TOKEN);
            return false;
        }
        List<SiteSummaryInfo> sites = siteList.getBody().getResult().getData();
        for (SiteSummaryInfo site : sites) {
            ResponseEntity<OperationResponseGridVoDeviceInfo> deviceList = omadaDeviceApi.getDeviceList(site.getSiteId(), 1, 1000);
            if (deviceList.getBody() == null) {
                continue;
            }
            List<DeviceInfo> devices = deviceList.getBody().getResult().getData();
            if (CollUtil.isEmpty(devices)) {
                continue;
            }
            List<String> macs = devices.stream().map(DeviceInfo::getMac).collect(Collectors.toList());
            List<SysDevice> sysDevices = SysDashboardConvert.INSTANCE.toSysDevices(devices);
            List<SysDevice> sysDeviceList = this.list(Wrappers.<SysDevice>lambdaQuery().in(SysDevice::getMac, macs));
            for (SysDevice device : sysDevices) {
                device.setSiteId(site.getSiteId());
                for (SysDevice sysDevice : sysDeviceList) {
                    if (Objects.equals(device.getMac(), sysDevice.getMac())) {
                        device.setId(sysDevice.getId());
                    }
                }
            }
            return this.saveOrUpdateBatch(sysDevices);
        }
        return true;
    }

    @Override
    public boolean settingJob() {
        // 启用Omada历史记录保留
        ResponseEntity<OperationResponseHistoryRetentionOpenApiVo> dataRetentionRes = omadaHistoryDataRetentionApi.getDataRetention();
        if (dataRetentionRes.getBody() == null) {
            return false;
        }
        HistoryRetentionOpenApiVo historyRetention = dataRetentionRes.getBody().getResult();

        if (!historyRetention.getClientsDataEnable()) {
            ModifyHistoryRetentionOpenApiVo modify = new ModifyHistoryRetentionOpenApiVo();
            modify.setClientsDataEnable(true);
            modify.setClientHistory(31);
            modify.setKnownClient(31);
            modify.setDaily(90);
            modify.setWeekly(180);
            modify.setPortalAuth(31);
            modify.setLog(31);
            modify.setRogueAp(31);
            omadaHistoryDataRetentionApi.modifyRetention(modify);
        }
        return true;
    }

    @Override
    public String testJob() {
        ResponseEntity<OperationResponseGridVoSiteSummaryInfo> siteList = omadaSiteApi.getSiteList(1, 1000);
        if (siteList.getBody() != null && siteList.getBody().getErrorCode() == OMADA_SUCCESS_CODE) {
            return "success";
        }
        return siteList.getBody().getMsg();
    }

    @Override
    public boolean forgetDevice(String siteId, String deviceMac) {
        ResponseEntity<OperationResponseWithoutResult> response = omadaDeviceApi.forgetDevice(siteId, deviceMac);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return true;
    }

    @Override
    public boolean addDeviceBySn(String siteId, DeviceListAddBySnOpenApiVo deviceListAddBySnOpenApiVo) {
        ResponseEntity<OperationResponseDeviceAddRespOpenApiVo> response = omadaDeviceApi.addDevicesBySn(siteId, deviceListAddBySnOpenApiVo);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return true;
    }

    @Override
    public boolean startAdoptDevice(String siteId, String deviceMac, AdoptDeviceRequest adoptDeviceRequest) {
        ResponseEntity<OperationResponseWithoutResult> response = omadaDeviceApi.adoptDevice(siteId, deviceMac, adoptDeviceRequest);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return true;
    }

    @Override
    public boolean rebootDevice(String siteId, String deviceMac) {
        ResponseEntity<OperationResponseWithoutResult> response = omadaDeviceApi.rebootDevice(siteId, deviceMac);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return true;
    }

    @Override
    public boolean updateConfig(String siteId, String deviceMac, ApGeneralConfig apGeneralConfig) {
        ResponseEntity<OperationResponseWithoutResult> response = omadaApApi.modifyGeneralConfig2(siteId, deviceMac, apGeneralConfig);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return true;
    }

    @Override
    public ApGeneralConfig getConfig(String siteId, String deviceMac) {
        ResponseEntity<OperationResponseApGeneralConfig> response = omadaApApi.getGeneralConfig2(siteId, deviceMac);

        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return response.getBody().getResult();
    }

    @Override
    public TableDataInfo getDeviceList(String siteId, Integer pageNum, Integer pageSize, String searchKey) {
        ResponseEntity<OperationResponseGridVoDeviceInfo> response = omadaDeviceApi.getDeviceList(siteId, pageNum, pageSize, searchKey);
        ResponseUtils.checkResponse(Objects.requireNonNull(response.getBody()).getErrorCode(), response.getBody().getMsg());
        return PageUtils.getDataTable(response.getBody().getResult().getData(), response.getBody().getResult().getTotalRows());
    }
}
