package com.mini.capi.sys.service;

import com.mini.capi.biz.domain.*;
import com.mini.capi.biz.service.*;
import com.mini.capi.model.ApiResult;
import com.mini.capi.utils.HostInfo;
import com.mini.capi.utils.vDate;
import com.mini.capi.utils.vId;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class DockerService {



    @Resource
    private SshInfoService sshInfoService;

    @Resource
    private SshUserService sshUserService;

    @Resource
    private DockerHostService dockerHostService;

    @Resource
    private DiskMountService diskMountService;

    @Resource
    private SysHostService sysHostService;


    @Resource
    private Executor hostExecutor;


    /**
     * 获取容器主机的磁盘使用情况
     */
    public ApiResult<?> jobHostDisk() {
        try {
            List<DockerHost> dockerHosts = dockerHostService.list();
            List<String> errorList = Collections.synchronizedList(new ArrayList<>());
            // 并行处理所有宿主机
            CompletableFuture<?>[] futures = dockerHosts.stream()
                    .map(host -> CompletableFuture.runAsync(() -> handleSingleHost(host, errorList), hostExecutor))
                    .toArray(CompletableFuture[]::new);
            // 等待全部完成
            CompletableFuture.allOf(futures).join();
            return errorList.isEmpty()
                    ? ApiResult.success()
                    : ApiResult.error();
        } catch (Exception e) {
            return ApiResult.error(101, e.getMessage());
        }
    }


    private void handleSingleHost(DockerHost host, List<String> errorList) {
        try {
            SshUser sshUser = sshUserService.getById(host.getUserId());
            SshInfo sshInfo = sshInfoService.getById(host.getHostId());
            /* 1. 采集实时数据 */
            HostInfo.Result r = HostInfo.collect(
                    sshInfo.getHostIp(),
                    Integer.parseInt(sshInfo.getHostPort()),
                    sshUser.getCUsername(),
                    sshUser.getCPassword());
            /* 2. 主机维度 saveOrUpdate */
            SysHost sysHost = r.host;
            sysHost.setSysHostId(host.getHostId());
            sysHost.setUpdateTime(vDate.getNow());
            sysHost.setDokerHostId(host.getDokerHostId());
            sysHostService.saveOrUpdate(sysHost);
            /* 3. 处理磁盘：先查库做索引，再比对 */
            List<DiskMount> dbDisks = diskMountService.lambdaQuery()
                    .eq(DiskMount::getSysHostId, host.getHostId())
                    .list();
            Map<String, DiskMount> dbDiskMap = dbDisks.stream()
                    .collect(Collectors.toMap(DiskMount::getMountPoint, Function.identity()));

            List<DiskMount> toSaveOrUpdate = new ArrayList<>();
            Set<String> liveMountPoint = new HashSet<>();
            for (DiskMount d : r.disks) {
                liveMountPoint.add(d.getMountPoint());
                DiskMount exist = dbDiskMap.get(d.getMountPoint());
                if (exist != null) {
                    d.setDiskMountId(exist.getDiskMountId());
                } else {
                    d.setDiskMountId(vId.getUid());
                }
                d.setSysHostId(host.getHostId());
                d.setUpdateTime(vDate.getNow());
                toSaveOrUpdate.add(d);
            }
            /* 4. 批量保存/更新 */
            diskMountService.saveOrUpdateBatch(toSaveOrUpdate);
            /* 5. 删除实时已消失的盘 */
            List<String> delIds = dbDisks.stream()
                    .filter(d -> !liveMountPoint.contains(d.getMountPoint()))
                    .map(DiskMount::getDiskMountId)
                    .collect(Collectors.toList());
            if (!delIds.isEmpty()) {
                diskMountService.removeByIds(delIds);
            }
        } catch (Exception e) {
            // 仅记录异常，不中断其它任务
            errorList.add(String.format("hostId=%s, error=%s", host.getHostId(), e.getMessage()));
        }
    }
}
