package org.wfc.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.wfc.common.core.domain.LoginUser;
import org.wfc.common.security.utils.SecurityUtils;
import org.wfc.omada.api.client.OmadaClientApi;
import org.wfc.omada.api.client.OmadaClientInsightApi;
import org.wfc.omada.api.client.model.ClientHistoryInfo;
import org.wfc.omada.api.client.model.ClientInfo;
import org.wfc.omada.api.client.model.OperationResponseClientGridVoClientInfo;
import org.wfc.omada.api.client.model.OperationResponseGridVoClientHistoryInfo;
import org.wfc.omada.api.device.OmadaDeviceApi;
import org.wfc.omada.api.device.model.DeviceInfo;
import org.wfc.omada.api.device.model.OperationResponseGridVoDeviceInfo;
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.user.api.IWifiApi;
import org.wfc.user.domain.UAccount;
import org.wfc.user.domain.UCdr;
import org.wfc.user.domain.UCdrHistory;
import org.wfc.user.domain.UClient;
import org.wfc.user.domain.UDevice;
import org.wfc.user.domain.bo.UCdrClientBo;
import org.wfc.user.domain.vo.UCdrClientVo;
import org.wfc.user.domain.vo.UCdrHistoryUserVo;
import org.wfc.user.domain.vo.UCdrUserVo;
import org.wfc.user.mapper.UCdrMapper;
import org.wfc.user.service.IUAccountService;
import org.wfc.user.service.IUCdrHistoryService;
import org.wfc.user.service.IUCdrService;
import org.wfc.user.service.IUClientService;
import org.wfc.user.service.IUDeviceService;
import org.wfc.user.util.AccountUtil;

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

/**
 * <p>
 * 用户平台_用户话单表 服务实现类
 * </p>
 *
 * @author cyc
 * @since 2024-12-09
 */
@Service
public class UCdrServiceImpl extends ServiceImpl<UCdrMapper, UCdr> implements IUCdrService {

    @Autowired
    private OmadaSiteApi omadaSiteApi;

    @Autowired
    private OmadaDeviceApi omadaDeviceApi;

    @Autowired
    private OmadaClientApi omadaClientApi;

    @Autowired
    private OmadaClientInsightApi omadaClientInsightApi;

    @Autowired
    private IUDeviceService deviceService;

    @Autowired
    private IUClientService clientService;

    @Autowired
    private IUCdrHistoryService cdrHistoryService;

    @Autowired
    private IUAccountService accountService;

    @Autowired
    private IWifiApi wifiApi;


    @Override
    public UCdrUserVo getByUser() {
        LoginUser<Object> loginUser = SecurityUtils.getLoginUser();
        List<UCdrUserVo> cdrUsers = this.baseMapper.getByUser(loginUser.getUserid(), null, null);
        return cdrUsers.stream().findFirst().orElse(null);
    }

    @Override
    public List<UCdrClientVo> getByClient(UCdrClientBo client) {
        return this.baseMapper.getByClient(client);
    }

    @Override
    public List<UCdrHistoryUserVo> getHistoryByUser() {
        LoginUser<Object> loginUser = SecurityUtils.getLoginUser();
        return this.baseMapper.getHistoryByUser(loginUser.getUserid());
    }

    @Override
    public void addCdrInfoByOmadaApi() {
        ResponseEntity<OperationResponseGridVoSiteSummaryInfo> siteResp = omadaSiteApi.getSiteList(1, 1000);
        if (ObjectUtil.isNull(siteResp.getBody())) {
            return;
        }
        List<SiteSummaryInfo> sites = siteResp.getBody().getResult().getData();
        List<UClient> allClients = clientService.list(Wrappers.<UClient>lambdaQuery().isNotNull(UClient::getUserId));
        // 添加AP设备
        addDevices(sites);
        for (SiteSummaryInfo site : sites) {
            ResponseEntity<OperationResponseClientGridVoClientInfo> clientResp = omadaClientApi.getGridActiveClients(site.getSiteId(), 1, 1000);
            if (ObjectUtil.isNull(clientResp.getBody())) {
                continue;
            }
            List<ClientInfo> clients = clientResp.getBody().getResult().getData();
            authClients(clients);

            for (ClientInfo client : clients) {
                // 添加用户设备
                UClient hasClient = addClient(client);
                // 添加话单
                addCdr(client, hasClient);
            }
            for (UClient client : allClients) {
                UCdr uCdr = this.getOne(Wrappers.<UCdr>lambdaQuery().eq(UCdr::getUserId, client.getUserId())
                        .eq(UCdr::getClientId, client.getId()), false);
                if (ObjectUtil.isNotNull(uCdr)) {
                    addCdrHistory(site, client.getClientMac(), uCdr.getId());
                }
            }
        }

        accountService.statAndCancelAuthUser();
    }

    private void authClients(List<ClientInfo> clients) {
        List<String> clientMacs = clients.stream().filter(c -> ObjectUtil.isNotNull(c.getAuthStatus()) && c.getAuthStatus() != 2)
                .map(ClientInfo::getMac).collect(Collectors.toList());
        if (CollUtil.isEmpty(clientMacs)) {
            return;
        }
        List<UClient> unAuthClients = clientService.list(Wrappers.<UClient>lambdaQuery().isNotNull(UClient::getUserId).in(UClient::getClientMac, clientMacs));
        List<Long> userIds = unAuthClients.stream().map(UClient::getUserId).collect(Collectors.toList());
        if (CollUtil.isEmpty(userIds)) {
            return;
        }
        List<UAccount> accounts = accountService.list(Wrappers.<UAccount>lambdaQuery().in(UAccount::getUserId, userIds));
        for (UClient unAuthClient : unAuthClients) {
            for (UAccount account : accounts) {
                if (Objects.equals(unAuthClient.getUserId(), account.getUserId())) {
                    if (AccountUtil.isValid(account, new Date())) {
                        wifiApi.authClient(unAuthClient.getSiteId(), unAuthClient.getClientMac());
                    }
                }
            }

        }
    }

    private void addCdrHistory(SiteSummaryInfo site, String mac, Long cdrId) {
        // 话单历史
        ResponseEntity<OperationResponseGridVoClientHistoryInfo> pastConnResp = omadaClientInsightApi.getGridPastConnections(site.getSiteId(), 1, 1000, mac);
        if (ObjectUtil.isNull(pastConnResp.getBody())) {
            return;
        }
        List<ClientHistoryInfo> pastConns = pastConnResp.getBody().getResult().getData();
        for (ClientHistoryInfo pastConn : pastConns) {
            UCdrHistory hasCdrHistory = cdrHistoryService.getOne(Wrappers.<UCdrHistory>lambdaQuery().eq(UCdrHistory::getCdrId, cdrId).eq(UCdrHistory::getStartTime, pastConn.getFirstSeen()), false);
            if (ObjectUtil.isNotNull(hasCdrHistory)) {
                continue;
            }
            UCdrHistory uCdrHistory = UCdrHistory.builder().cdrId(cdrId).startTime(pastConn.getFirstSeen())
                    .endTime(pastConn.getLastSeen())
                    .trafficUp(pastConn.getUpload())
                    .trafficDown(pastConn.getDownload())
                    .duration(pastConn.getDuration())
                    .build();

            cdrHistoryService.save(uCdrHistory);
        }
    }

    private Long addCdr(ClientInfo client, UClient hasClient) {
        // 话单
        UCdr hasUCdr = this.getOne(Wrappers.<UCdr>lambdaQuery()
                .eq(ObjectUtil.isNotNull(hasClient.getUserId()), UCdr::getUserId, hasClient.getUserId())
                .eq(UCdr::getClientId, hasClient.getId()), false);
        Long cdrId = null;
        if (ObjectUtil.isNotNull(hasUCdr)) {
            cdrId = hasUCdr.getId();
        }
        UDevice hasDevice = deviceService.getOne(Wrappers.<UDevice>lambdaQuery().eq(UDevice::getDeviceMac, client.getApMac()), false);
        UCdr uCdr = UCdr.builder().clientId(hasClient.getId())
                .userId(hasClient.getUserId())
                .deviceId(hasDevice.getId())
                .ssid(client.getSsid())
                .rxRate(client.getRxRate())
                .txRate(client.getTxRate())
                .lastSeenTime(client.getLastSeen())
                .upTime(client.getUptime())
                .upPacket(client.getUpPacket())
                .downPacket(client.getDownPacket())
                .trafficDown(client.getTrafficDown())
                .trafficUp(client.getTrafficUp())
                .activity(client.getActivity())
                .build();
        uCdr.setId(cdrId);
        this.saveOrUpdate(uCdr);
        return uCdr.getId();
    }

    private UClient addClient(ClientInfo client) {
        // 用户设备
        UClient hasClient = clientService.getOne(Wrappers.<UClient>lambdaQuery().eq(UClient::getClientMac, client.getMac()), false);
        Long clientId = null;
        Long userId = null;
        if (ObjectUtil.isNotNull(hasClient)) {
            clientId = hasClient.getId();
            userId = hasClient.getUserId();
        }
        UClient uClient = UClient.builder().clientMac(client.getMac())
                .userId(userId)
                .clientName(client.getName())
                .clientDeviceType(client.getDeviceType())
                .build();
        uClient.setId(clientId);
        clientService.saveOrUpdate(uClient);
        return uClient;
    }

    private void addDevices(List<SiteSummaryInfo> sites) {
        // ap设备
        for (SiteSummaryInfo site : sites) {
            ResponseEntity<OperationResponseGridVoDeviceInfo> deviceResp = omadaDeviceApi.getDeviceList(site.getSiteId(), 1, 1000);
            if (ObjectUtil.isNull(deviceResp.getBody())) {
                return;
            }
            List<DeviceInfo> devices = deviceResp.getBody().getResult().getData();
            for (DeviceInfo device : devices) {
                UDevice hasUDevice = deviceService.getOne(Wrappers.<UDevice>lambdaQuery().eq(UDevice::getDeviceMac, device.getMac()), false);
                if (ObjectUtil.isNotNull(hasUDevice)) {
                    continue;
                }
                UDevice uDevice = UDevice.builder().deviceIp(device.getIp())
                        .deviceMac(device.getMac())
                        .deviceName(device.getName())
                        .deviceModel(device.getModel())
                        .build();
                deviceService.save(uDevice);
            }
        }
    }

}
