#!/bin/bash
# 根据设备唯一标识生成唯一 MAC 地址和 DUID
# 解决多台设备烧写同一镜像后 MAC/IP 冲突问题

set -e

# MAC 地址厂商前缀（ST Microelectronics OUI）
MAC_PREFIX="38:D5:47"

# 检查必要工具
check_deps() {
    local missing=()
    for cmd in ip md5sum; do
        command -v "${cmd}" &>/dev/null || missing+=("${cmd}")
    done
    if [[ ${#missing[@]} -gt 0 ]]; then
        echo "ERROR: 缺少必要工具: ${missing[*]}" >&2
        exit 1
    fi
}

# 获取设备唯一标识符
# 优先级: DevSN > CPU序列号 > 随机值
get_device_unique_id() {
    local unique_id

    # 1. 首先尝试从 /etc/environment 读取 DevSN（用户配置的唯一标识）
    if [[ -f /etc/environment ]]; then
        unique_id=$(grep "^DevSN=" /etc/environment 2>/dev/null | cut -d'=' -f2 | tr -d '"' | head -1)
        if [[ -n "${unique_id}" ]]; then
            echo "DevSN:${unique_id}"
            return
        fi
    fi

    # 2. 尝试从 /proc/cpuinfo 获取 CPU 序列号
    unique_id=$(cat /proc/cpuinfo 2>/dev/null | grep "Serial" | awk '{print $3}' | head -1)

    # 3. 如果为空，尝试从设备树获取
    if [[ -z "${unique_id}" ]] && [[ -f /sys/firmware/devicetree/base/serial-number ]]; then
        unique_id=$(cat /sys/firmware/devicetree/base/serial-number 2>/dev/null | tr -d '\0')
    fi

    if [[ -n "${unique_id}" ]]; then
        echo "CPU:${unique_id}"
        return
    fi

    # 4. 使用随机值
    unique_id=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "random-$$-$(date +%s)")
    echo "Random:${unique_id}"
}

# 从序列号生成 MAC 地址
# 格式: 38:D5:47:XX:XX:XX (保留厂商前缀，后3字节从序列号派生)
generate_mac() {
    local serial="$1"
    local iface="$2"

    # 使用序列号的哈希生成后3字节
    local hash
    hash=$(echo -n "${serial}${iface}" | md5sum | cut -c1-6)

    # 如果 hash 为空，生成随机值
    if [[ -z "${hash}" ]]; then
        hash=$(printf '%06x' $((RANDOM % 0xFFFFFF)))
    fi

    # 构造 MAC: 使用 MAC_PREFIX 常量
    printf "%s:%s" "${MAC_PREFIX}" "$(echo "${hash}" | sed 's/../&:/g; s/:$//')"
}

# 设置 MAC 地址
set_mac_address() {
    local iface="$1"
    local mac="$2"

    # 检查接口是否存在
    if ! ip link show "${iface}" &>/dev/null; then
        echo "接口 ${iface} 不存在，跳过"
        return 1
    fi

    # 获取当前 MAC
    local current_mac
    current_mac=$(cat /sys/class/net/${iface}/address 2>/dev/null)

    # 如果已经是目标 MAC，跳过
    if [[ "${current_mac,,}" == "${mac,,}" ]]; then
        echo "${iface}: MAC 地址已是 ${mac}，无需修改"
        return 0
    fi

    # 设置新 MAC
    echo "${iface}: 设置 MAC 地址 ${mac} (原: ${current_mac})"
    ip link set "${iface}" down
    ip link set "${iface}" address "${mac}"
    ip link set "${iface}" up

    echo "${iface}: MAC 地址已更新为 ${mac}"
}

# 确保 machine-id 唯一
ensure_unique_machine_id() {
    local device_id="$1"
    local marker_file="/etc/.aethex_machine_id_set"
    local id_record_file="/etc/.aethex_device_id"

    # 计算新的 machine-id
    local new_id
    new_id=$(echo -n "${device_id}" | md5sum | cut -c1-32)

    # 检查是否需要重新生成
    local need_regenerate=false

    if [[ ! -f "${marker_file}" ]]; then
        echo "首次设置 machine-id"
        need_regenerate=true
    elif [[ -f "${id_record_file}" ]]; then
        local recorded_id
        recorded_id=$(cat "${id_record_file}" 2>/dev/null)
        if [[ "${recorded_id}" != "${device_id}" ]]; then
            echo "设备标识已变更: ${recorded_id} -> ${device_id}"
            need_regenerate=true
        fi
    else
        # 标记文件存在但无记录，检查当前 machine-id 是否匹配
        local current_id
        current_id=$(cat /etc/machine-id 2>/dev/null)
        if [[ "${current_id}" != "${new_id}" ]]; then
            echo "machine-id 与设备标识不匹配，重新生成"
            need_regenerate=true
        fi
    fi

    if [[ "${need_regenerate}" == "true" ]]; then
        local current_id
        current_id=$(cat /etc/machine-id 2>/dev/null)
        echo "更新 machine-id: ${current_id} -> ${new_id}"
        echo "${new_id}" > /etc/machine-id

        # 记录设备标识
        echo "${device_id}" > "${id_record_file}"

        # 清除 DUID 缓存，强制重新生成
        rm -f /var/lib/systemd/network/dhcp*
        rm -f /var/lib/systemd/dhcp*

        # 标记已设置
        touch "${marker_file}"
        echo "machine-id 已更新，DUID 将重新生成"
    else
        echo "machine-id 已是唯一值"
        touch "${marker_file}"
    fi
}

# 配置 systemd-networkd 使用 link-layer DUID
configure_duid_type() {
    local network_dir="/etc/systemd/network"
    local marker_file="/etc/.aethex_duid_configured"

    # 如果已经配置过，跳过
    if [[ -f "${marker_file}" ]]; then
        echo "DUID 配置已设置过，跳过"
        return 0
    fi

    # 遍历所有网络配置文件
    for net_file in "${network_dir}"/*.network; do
        [[ -f "${net_file}" ]] || continue

        # 检查是否已有 DUIDType 配置
        if grep -q "DUIDType" "${net_file}"; then
            echo "${net_file} 已有 DUIDType 配置"
            continue
        fi

        # 添加 [DHCPv4] 或 [DHCP] 段的 DUIDType
        echo "配置 ${net_file} 使用 link-layer DUID..."

        # 检查是否有 [DHCPv4] 段
        if grep -q "\\[DHCPv4\\]" "${net_file}"; then
            sed -i '/\[DHCPv4\]/a DUIDType=link-layer' "${net_file}"
        elif grep -q "\\[DHCP\\]" "${net_file}"; then
            sed -i '/\[DHCP\]/a DUIDType=link-layer' "${net_file}"
        else
            # 添加 [DHCPv4] 段
            echo "" >> "${net_file}"
            echo "[DHCPv4]" >> "${net_file}"
            echo "DUIDType=link-layer" >> "${net_file}"
        fi
    done

    touch "${marker_file}"
    echo "DUID 配置完成"
}

# 主流程
main() {
    echo "=== 设置唯一 MAC 地址和 DUID ==="

    # 检查依赖
    check_deps

    # 获取设备唯一标识
    local device_id
    device_id=$(get_device_unique_id)

    # 提取实际值（去掉前缀）
    local id_value="${device_id#*:}"
    local id_type="${device_id%%:*}"

    echo "设备标识类型: ${id_type}"
    echo "设备唯一标识: ${id_value}"

    # 1. 确保 machine-id 唯一
    ensure_unique_machine_id "${id_value}"
    echo ""

    # 2. 配置 DUID 类型
    configure_duid_type
    echo ""

    # 3. 设置 end1 的 MAC (主网口)
    local mac_end1
    mac_end1=$(generate_mac "${id_value}" "end1")
    set_mac_address "end1" "${mac_end1}"

    # 4. 设置 end2 的 MAC (备用网口)
    local mac_end2
    mac_end2=$(generate_mac "${id_value}" "end2")
    set_mac_address "end2" "${mac_end2}"

    echo ""
    echo "=== 完成 ==="
    echo "注意: 如果 IP 未变化，请重启设备或等待 DHCP 租约过期"
}

main "$@"
