package hostid

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

// GetRootDiskSerial 返回承载根文件系统的物理磁盘序列号。
func GetRootDiskSerial() (string, error) {
	// 1. 找 "/" 的 major:minor
	f, _ := os.Open("/proc/self/mountinfo")
	defer f.Close()

	var major, minor int
	sc := bufio.NewScanner(f)
	for sc.Scan() {
		p := strings.Split(sc.Text(), " ")
		if len(p) > 4 && p[4] == "/" {
			mm := strings.Split(p[2], ":")
			major, _ = strconv.Atoi(mm[0])
			minor, _ = strconv.Atoi(mm[1])
			break
		}
	}
	if major == 0 && minor == 0 {
		return "", fmt.Errorf("root mount not found")
	}

	// 2. /sys/dev/block/major:minor → 解析符号链接，向上回溯直到
	//    /sys/block/<disk> 存在，适配 nvme0n1p2、mmcblk0p1、dm-0 等所有情况
	link := fmt.Sprintf("/sys/dev/block/%d:%d", major, minor)
	target, err := os.Readlink(link)
	if err != nil {
		return "", err
	}
	path := filepath.Clean(filepath.Join(filepath.Dir(link), target))

	var disk string
	for {
		name := filepath.Base(path) // 当前层目录名
		if _, err := os.Stat(filepath.Join("/sys/block", name)); err == nil {
			disk = name // 找到顶层物理盘
			break
		}
		parent := filepath.Dir(path)
		if parent == path { // 已到根还没找到
			return "", fmt.Errorf("disk name not found via %s", link)
		}
		path = parent
	}

	// 3. 读取序列号
	candidates := []string{
		"/sys/block/" + disk + "/device/serial",
		"/sys/block/" + disk + "/serial",
		"/sys/block/" + disk + "/device/vpd_unit_serial",
		"/sys/block/" + disk + "/device/wwid",
	}
	for _, p := range candidates {
		if b, err := os.ReadFile(p); err == nil {
			s := strings.TrimSpace(string(b))
			if s != "" {
				return s, nil
			}
		}
	}
	return "", fmt.Errorf("serial not found for %s", disk)
}
