const crypto = require("node:crypto")
const os = require("node:os")
const { readFileSync } = require("fs")
const { execSync } = require("child_process")

function getDiskSerial() {
    try {
        let command
        if (os.platform() === "win32") {
            command = "wmic diskdrive get serialnumber"
            const output = execSync(command).toString()
            const serial = output.split("\n")[1].trim()
            return serial
        } else if (os.platform() === "darwin") {
            command = "system_profiler SPHardwareDataType | grep 'Serial Number'"
            const output = execSync(command).toString()
            const serial = output.match(/Serial Number: (.+)/)?.[1]?.trim()
            return serial
        } else if (os.platform() === "linux") {
            const serialPath = "/sys/class/block/sda/device/serial"
            const serial = readFileSync(serialPath, "utf8").trim()
            return serial
        } else {
            throw new Error("Unsupported OS")
        }
    } catch (error) {
        console.error("Error retrieving disk serial number:", error)
        return ""
    }
}

function getMotherboardSerial() {
    try {
        let command
        if (os.platform() === "win32") {
            command = "wmic baseboard get serialnumber"
            const output = execSync(command).toString()
            const serial = output.split("\n")[1].trim()
            return serial
        } else if (os.platform() === "darwin") {
            command = "ioreg -l | grep IOPlatformSerialNumber"
            const output = execSync(command).toString()
            const serial = output.match(/"IOPlatformSerialNumber" = "(.+?)"/)?.[1]?.trim()
            return serial
        } else if (os.platform() === "linux") {
            const serialPath = "/sys/class/dmi/id/board_serial"
            const serial = readFileSync(serialPath, "utf8").trim()
            return serial
        } else {
            throw new Error("Unsupported OS")
        }
    } catch (error) {
        console.error("Error retrieving motherboard serial number:", error)
        return ""
    }
}

function getMacAddresses() {
    const networkInterfaces = os.networkInterfaces()
    const macs = []

    for (const iface of Object.values(networkInterfaces)) {
        for (const nic of iface) {
            if (!nic.internal && nic.mac !== "00:00:00:00:00:00") {
                macs.push(nic.mac)
            }
        }
    }

    return macs.join("")
}

function generateHWID() {
    const diskSerial = getDiskSerial()
    const motherboardSerial = getMotherboardSerial()
    const macAddresses = getMacAddresses()
    const cpuInfo = os.cpus().map(cpu => cpu.model).join("")
    const user = os.userInfo().username

    const uniqueData = `${diskSerial}-${motherboardSerial}-${macAddresses}-${cpuInfo}-${user}`
    const hwid = crypto.createHash("sha256").update(uniqueData).digest("hex")

    return hwid
}

module.exports.getHWID = generateHWID