package com.qqchen.deploy.backend.framework.ssh.impl;

import com.qqchen.deploy.backend.framework.dto.CommandResult;
import com.qqchen.deploy.backend.framework.dto.DiskInfo;
import com.qqchen.deploy.backend.framework.dto.DiskUsageInfo;
import com.qqchen.deploy.backend.framework.dto.MonitorData;
import com.qqchen.deploy.backend.framework.enums.OsTypeEnum;
import com.qqchen.deploy.backend.framework.ssh.AbstractSSHCommandService;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Windows SSH命令服务实现（Framework层）
 * 需要Windows服务器安装OpenSSH Server
 */
@Slf4j
@Service
public class WindowsSSHCommandServiceImpl extends AbstractSSHCommandService {
    
    // ==================== 命令常量 ====================
    
    /**
     * CPU使用率命令
     */
    private static final String CMD_CPU_USAGE = 
        "powershell \"Get-Counter '\\Processor(_Total)\\% Processor Time' | " +
        "Select-Object -ExpandProperty CounterSamples | " +
        "Select-Object -ExpandProperty CookedValue\"";
    
    /**
     * 内存使用率命令
     */
    private static final String CMD_MEMORY_USAGE = 
        "powershell \"$os = Get-CimInstance Win32_OperatingSystem; " +
        "$total = $os.TotalVisibleMemorySize; " +
        "$free = $os.FreePhysicalMemory; " +
        "$used = $total - $free; " +
        "[math]::Round(($used / $total) * 100, 2)\"";
    
    /**
     * 磁盘使用率命令（格式：驱动器号|文件系统|总容量|已用|使用率）
     */
    private static final String CMD_DISK_USAGE = 
        "powershell \"Get-Volume | " +
        "Where-Object {$_.DriveLetter -ne $null -and $_.Size -gt 0} | " +
        "ForEach-Object {" +
        "  $used = [math]::Round(($_.Size - $_.SizeRemaining)/1GB, 2); " +
        "  $total = [math]::Round($_.Size/1GB, 2); " +
        "  $percent = [math]::Round((($_.Size - $_.SizeRemaining)/$_.Size)*100, 2); " +
        "  $_.DriveLetter + '|' + $_.FileSystemType + '|' + $total + '|' + $used + '|' + $percent" +
        "}\"";
    
    /**
     * 网络接收流量命令(KB)
     */
    private static final String CMD_NETWORK_RX = 
        "powershell \"Get-NetAdapterStatistics | " +
        "Where-Object {$_.Name -notlike '*Loopback*' -and $_.Name -notlike '*Virtual*'} | " +
        "Measure-Object -Property ReceivedBytes -Sum | " +
        "Select-Object -ExpandProperty Sum | " +
        "ForEach-Object {[math]::Round($_ / 1KB)}\"";
    
    /**
     * 网络发送流量命令(KB)
     */
    private static final String CMD_NETWORK_TX = 
        "powershell \"Get-NetAdapterStatistics | " +
        "Where-Object {$_.Name -notlike '*Loopback*' -and $_.Name -notlike '*Virtual*'} | " +
        "Measure-Object -Property SentBytes -Sum | " +
        "Select-Object -ExpandProperty Sum | " +
        "ForEach-Object {[math]::Round($_ / 1KB)}\"";
    
    // ==================== 实现方法 ====================
    
    @Override
    public String getHostname(SSHClient sshClient) {
        return safeExecute(sshClient, "hostname");
    }
    
    @Override
    public String getOsVersion(SSHClient sshClient) {
        // Windows版本信息
        return safeExecute(sshClient, "ver");
    }
    
    @Override
    public Integer getCpuCores(SSHClient sshClient) {
        // 使用环境变量获取CPU核心数
        String result = safeExecute(sshClient, "echo %NUMBER_OF_PROCESSORS%");
        return parseInteger(result);
    }
    
    @Override
    public Integer getMemorySize(SSHClient sshClient) {
        // 使用PowerShell获取内存大小（GB）
        String command = "powershell \"(Get-CimInstance Win32_PhysicalMemory | " +
                        "Measure-Object -Property capacity -Sum).sum /1gb\"";
        String result = safeExecute(sshClient, command);
        return parseInteger(result);
    }
    
    @Override
    public List<DiskInfo> getDiskInfo(SSHClient sshClient) {
        // 使用PowerShell获取所有硬盘分区信息，包含驱动器号、文件系统类型和总容量
        // 输出格式: 驱动器号|文件系统类型|总容量(GB)
        String command = "powershell \"Get-Volume | " +
                        "Where-Object {$_.DriveLetter -ne $null -and $_.Size -gt 0} | " +
                        "ForEach-Object {$_.DriveLetter + '|' + $_.FileSystemType + '|' + [math]::Round($_.Size/1GB, 2)}\"";
        String result = safeExecute(sshClient, command);
        
        List<DiskInfo> diskList = new ArrayList<>();
        Set<String> seenDrives = new HashSet<>();
        
        if (result != null && !result.trim().isEmpty()) {
            String[] lines = result.trim().split("\\n");
            for (String line : lines) {
                String[] parts = line.split("\\|");
                if (parts.length >= 3) {
                    try {
                        String driveLetter = parts[0].trim();
                        String fileSystem = parts[1].trim();
                        String sizeStr = parts[2].trim();
                        
                        // 去重：同一驱动器号只记录一次
                        if (seenDrives.contains(driveLetter)) {
                            log.debug("跳过重复驱动器: {}", driveLetter);
                            continue;
                        }
                        seenDrives.add(driveLetter);
                        
                        // 只保留本地物理磁盘，排除网络驱动器等
                        // Windows常见文件系统：NTFS, ReFS, FAT32
                        if (fileSystem == null || fileSystem.isEmpty()) {
                            fileSystem = "NTFS"; // 默认NTFS
                        }
                        
                        DiskInfo diskInfo = DiskInfo.builder()
                            .mountPoint(driveLetter + ":")
                            .fileSystem(fileSystem)
                            .totalSize(new BigDecimal(sizeStr))
                            .build();
                        diskList.add(diskInfo);
                    } catch (NumberFormatException e) {
                        log.warn("解析磁盘信息失败: {}", line, e);
                    }
                }
            }
        }
        return diskList;
    }
    
    @Override
    public BigDecimal getCpuUsage(SSHClient sshClient) {
        String result = safeExecute(sshClient, CMD_CPU_USAGE);
        return parseBigDecimal(result);
    }
    
    @Override
    public BigDecimal getMemoryUsage(SSHClient sshClient) {
        String result = safeExecute(sshClient, CMD_MEMORY_USAGE);
        return parseBigDecimal(result);
    }
    
    @Override
    public List<DiskUsageInfo> getDiskUsage(SSHClient sshClient) {
        String result = safeExecute(sshClient, CMD_DISK_USAGE);
        
        List<DiskUsageInfo> diskUsageList = new ArrayList<>();
        Set<String> seenDrives = new HashSet<>();
        
        if (result != null && !result.trim().isEmpty()) {
            String[] lines = result.trim().split("\\n");
            for (String line : lines) {
                String[] parts = line.split("\\|");
                if (parts.length >= 5) {
                    try {
                        String driveLetter = parts[0].trim();
                        String fileSystem = parts[1].trim();
                        String totalStr = parts[2].trim();
                        String usedStr = parts[3].trim();
                        String usageStr = parts[4].trim();
                        
                        // 去重
                        if (seenDrives.contains(driveLetter)) {
                            continue;
                        }
                        seenDrives.add(driveLetter);
                        
                        // 处理空的文件系统类型
                        if (fileSystem == null || fileSystem.isEmpty()) {
                            fileSystem = "NTFS";
                        }
                        
                        DiskUsageInfo diskUsage = DiskUsageInfo.builder()
                            .mountPoint(driveLetter + ":")
                            .fileSystem(fileSystem)
                            .totalSize(parseBigDecimal(totalStr))
                            .usedSize(parseBigDecimal(usedStr))
                            .usagePercent(parseBigDecimal(usageStr))
                            .build();
                        diskUsageList.add(diskUsage);
                    } catch (Exception e) {
                        log.warn("解析Windows磁盘使用率失败: {}", line, e);
                    }
                }
            }
        }
        return diskUsageList;
    }
    
    @Override
    public Long getNetworkRx(SSHClient sshClient) {
        String result = safeExecute(sshClient, CMD_NETWORK_RX);
        return parseLong(result);
    }
    
    @Override
    public Long getNetworkTx(SSHClient sshClient) {
        String result = safeExecute(sshClient, CMD_NETWORK_TX);
        return parseLong(result);
    }
    
    /**
     * 解析 Long 类型结果
     */
    private Long parseLong(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return Long.parseLong(value.trim());
        } catch (NumberFormatException e) {
            log.warn("解析Long失败: {}", value, e);
            return null;
        }
    }
    
    @Override
    public MonitorData collectMonitorData(SSHClient sshClient) {
        try {
            // 1. 准备5个PowerShell监控命令（使用统一的命令常量 ✅）
            List<String> commands = Arrays.asList(
                CMD_CPU_USAGE,
                CMD_MEMORY_USAGE,
                CMD_DISK_USAGE,
                CMD_NETWORK_RX,
                CMD_NETWORK_TX
            );
            
            // 2. 批量执行PowerShell命令（只需1次网络往返 ✅）
            List<CommandResult> results = executeCommands(sshClient, commands);
            
            // 3. 解析结果
            BigDecimal cpuUsage = parseCommandResultToBigDecimal(results.get(0));
            BigDecimal memoryUsage = parseCommandResultToBigDecimal(results.get(1));
            List<DiskUsageInfo> diskUsage = parseDiskUsageFromCommand(results.get(2));
            Long networkRx = parseCommandResultToLong(results.get(3));
            Long networkTx = parseCommandResultToLong(results.get(4));
            
            // 4. 构建监控数据
            return MonitorData.builder()
                .cpuUsage(cpuUsage)
                .memoryUsage(memoryUsage)
                .diskUsage(diskUsage)
                .networkRx(networkRx)
                .networkTx(networkTx)
                .build();
                
        } catch (Exception e) {
            log.error("批量采集Windows监控数据失败", e);
            return null;
        }
    }
    
    /**
     * 从CommandResult解析BigDecimal
     */
    private BigDecimal parseCommandResultToBigDecimal(CommandResult result) {
        if (result == null || !result.isSuccess() || result.getOutput() == null || result.getOutput().trim().isEmpty()) {
            return null;
        }
        return parseBigDecimal(result.getOutput());
    }
    
    /**
     * 从CommandResult解析Long
     */
    private Long parseCommandResultToLong(CommandResult result) {
        if (result == null || !result.isSuccess() || result.getOutput() == null || result.getOutput().trim().isEmpty()) {
            return null;
        }
        return parseLong(result.getOutput());
    }
    
    /**
     * 从CommandResult解析Windows磁盘使用率（格式：驱动器号|文件系统|总容量|已用|使用率）
     */
    private List<DiskUsageInfo> parseDiskUsageFromCommand(CommandResult result) {
        List<DiskUsageInfo> diskUsageList = new ArrayList<>();
        
        if (result == null || !result.isSuccess() || result.getOutput() == null || result.getOutput().trim().isEmpty()) {
            return diskUsageList;
        }
        
        Set<String> seenDrives = new HashSet<>();
        String[] lines = result.getOutput().trim().split("\\n");
        
        for (String line : lines) {
            String[] parts = line.split("\\|");
            if (parts.length >= 5) {
                try {
                    String driveLetter = parts[0].trim();
                    String fileSystem = parts[1].trim();
                    String totalStr = parts[2].trim();
                    String usedStr = parts[3].trim();
                    String usageStr = parts[4].trim();
                    
                    // 去重
                    if (seenDrives.contains(driveLetter)) {
                        continue;
                    }
                    seenDrives.add(driveLetter);
                    
                    // 处理空的文件系统类型
                    if (fileSystem == null || fileSystem.isEmpty()) {
                        fileSystem = "NTFS";
                    }
                    
                    DiskUsageInfo diskUsage = DiskUsageInfo.builder()
                        .mountPoint(driveLetter + ":")
                        .fileSystem(fileSystem)
                        .totalSize(parseBigDecimal(totalStr))
                        .usedSize(parseBigDecimal(usedStr))
                        .usagePercent(parseBigDecimal(usageStr))
                        .build();
                    diskUsageList.add(diskUsage);
                } catch (Exception e) {
                    log.warn("解析Windows磁盘使用率失败: {}", line, e);
                }
            }
        }
        
        return diskUsageList;
    }
    
    @Override
    public OsTypeEnum getSupportedOsType() {
        return OsTypeEnum.WINDOWS;
    }
}
