import random
import string
import re
import uuid
import os

# Константы для генерации серийного номера и MAC-адреса
BASE_CODE = "C02"
MODEL_CODE = "41"
LOCATION_CODES = ["KY", "KX", "KW", "KV", "KU", "KT"]
WEEK_CODES = ["Y", "X", "W", "V", "U", "T"]

# Функция генерации серийного номера для iMacPro1,1
def generate_serial_number():
    week_code = random.choice(WEEK_CODES)
    location_code = random.choice(LOCATION_CODES)
    unique_id = ''.join(random.choices('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=4))
    serial = BASE_CODE + week_code + MODEL_CODE + location_code + unique_id
    return serial

# Функция генерации последних 3 октетов MAC-адреса
def generate_mac_suffix():
    return ':'.join(['{:02X}'.format(random.randint(0, 255)) for _ in range(3)])

# Функция генерации полного MAC-адреса с заданными первыми 3 октетами
def generate_mac_address(oui="98:9e:63"):
    mac_suffix = generate_mac_suffix()
    mac_address = f"{oui}:{mac_suffix}"
    return mac_address

# Функция генерации ROM на основе MAC-адреса
def generate_rom(mac_address):
    # Удаляем двоеточия из MAC-адреса и переводим в верхний регистр
    rom = mac_address.replace(':', '').upper()
    return rom

# Функция генерации MLB (Main Logic Board Serial Number)
def generate_mlb(serial_number):
    # Дополняем серийный номер до 17 символов случайными символами
    mlb_suffix = ''.join(random.choices('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=5))
    mlb = serial_number + mlb_suffix
    return mlb

# Функция генерации UUID в формате VMware с пробелами и маленькими буквами
def generate_vmware_uuid():
    # Генерируем новый UUID
    new_uuid = uuid.uuid4()
    # Форматируем UUID в нужный вид
    new_uuid = ' '.join(new_uuid.hex[i:i+2] for i in range(0, 32, 2)).lower()
    return new_uuid

# Функция обновления конфигурационного файла виртуальной машины
def update_config_file(file_path):
    if not os.path.isfile(file_path):
        raise FileNotFoundError(f"Файл не найден: {file_path}")

    with open(file_path, 'r', encoding='windows-1251') as file:
        config_lines = file.readlines()

    # Генерация новых значений
    new_serial_number = generate_serial_number()
    new_mac_address = generate_mac_address()
    new_uuid = generate_vmware_uuid()
    new_mlb = generate_mlb(new_serial_number)
    new_rom = generate_rom(new_mac_address)

    # Создание нового списка строк конфигурационного файла
    new_config_lines = []
    # Флаги для отслеживания наличия параметров
    rom_line_found = False
    mlb_line_found = False
    serial_line_found = False
    mac_line_found = False
    uuid_bios_line_found = False
    uuid_location_line_found = False
    smc_version_found = False
    ethernet_address_type_found = False
    ethernet_generated_address_offset_found = False
    ethernet_generated_address_found = False
    hw_model_reflect_found = False
    serial_reflect_found = False
    smbios_reflect_found = False
    rom_reflect_found = False
    mlb_reflect_found = False
    board_id_found = False
    hw_model_found = False
    firmware_efi_found = False
    board_id_reflect_found = False

    # Множество для отслеживания обработанных ключей и предотвращения дублей
    seen_keys = set()

    # Переменная для отслеживания позиции после "firmware = \"efi\""
    insert_after_firmware = False

    for index, line in enumerate(config_lines):
        stripped_line = line.strip()

        # Пропускаем пустые строки и комментарии
        if not stripped_line or stripped_line.startswith('#'):
            new_config_lines.append(line)
            continue

        # Разделяем строку на ключ и значение
        if '=' in stripped_line:
            key, value = stripped_line.split('=', 1)
            key = key.strip()
            value = value.strip()

            # Проверяем, был ли ключ уже обработан
            if key in seen_keys:
                # Если ключ уже был добавлен, пропускаем текущую строку (удаляем дубликат)
                continue
            else:
                seen_keys.add(key)

            # Обновление серийного номера
            if key == 'serialNumber':
                line = f'serialNumber = "{new_serial_number}"\n'
                serial_line_found = True

            # Обновление MAC-адреса
            elif key.lower() == 'ethernet0.address':
                line = f'ethernet0.address = "{new_mac_address}"\n'
                mac_line_found = True

            # Обновление uuid.bios
            elif key == 'uuid.bios':
                line = f'uuid.bios = "{new_uuid}"\n'
                uuid_bios_line_found = True

            # Обновление uuid.location
            elif key == 'uuid.location':
                line = f'uuid.location = "{new_uuid}"\n'
                uuid_location_line_found = True

            # Обновление ROM
            elif key == 'efi.nvram.var.ROM':
                line = f'efi.nvram.var.ROM = "{new_rom}"\n'
                rom_line_found = True

            # Обновление MLB
            elif key == 'efi.nvram.var.MLB':
                line = f'efi.nvram.var.MLB = "{new_mlb}"\n'
                mlb_line_found = True

            # Обработка smc.version
            elif key == 'smc.version':
                line = 'smc.version = "0"\n'
                smc_version_found = True

            # Обработка ethernet0.addressType
            elif key == 'ethernet0.addressType':
                # Убедимся, что значение точно "static" без лишних кавычек
                line = 'ethernet0.addressType = "static"\n'
                ethernet_address_type_found = True

            # Обработка ethernet0.generatedAddressOffset
            elif key == 'ethernet0.generatedAddressOffset':
                if value.strip('"') == "0":
                    line = 'ethernet0.checkMACAddress = "FALSE"\n'
                ethernet_generated_address_offset_found = True

            # Обработка ethernet0.generatedAddress
            elif key == 'ethernet0.generatedAddress':
                line = f'ethernet0.address = "{new_mac_address}"\n'
                ethernet_generated_address_found = True

            # Обработка hw.model.reflectHost
            elif key == 'hw.model.reflectHost':
                line = 'hw.model.reflectHost = "FALSE"\n'
                hw_model_reflect_found = True

            # Обработка serialNumber.reflectHost
            elif key == 'serialNumber.reflectHost':
                line = 'serialNumber.reflectHost = "FALSE"\n'
                serial_reflect_found = True

            # Обработка smbios.reflectHost
            elif key == 'smbios.reflectHost':
                line = 'smbios.reflectHost = "FALSE"\n'
                smbios_reflect_found = True

            # Обработка efi.nvram.var.ROM.reflectHost
            elif key == 'efi.nvram.var.ROM.reflectHost':
                line = 'efi.nvram.var.ROM.reflectHost = "FALSE"\n'
                rom_reflect_found = True

            # Обработка efi.nvram.var.MLB.reflectHost
            elif key == 'efi.nvram.var.MLB.reflectHost':
                line = 'efi.nvram.var.MLB.reflectHost = "FALSE"\n'
                mlb_reflect_found = True

            # Проверка наличия firmware = "efi"
            elif key == 'firmware' and value.strip('"').lower() == 'efi':
                firmware_efi_found = True
                # После этой строки вставим необходимые параметры, если они отсутствуют
                new_config_lines.append(line)
                # Вставка после "firmware = \"efi\""
                # Флаг для вставки следующих строк
                insert_after_firmware = True
                continue

            # Проверка наличия board-id
            elif key == 'board-id':
                board_id_found = True

            # Проверка наличия hw.model
            elif key == 'hw.model':
                hw_model_found = True

            # Проверка наличия board-id.reflectHost
            elif key == 'board-id.reflectHost':
                board_id_reflect_found = True

        # Добавляем (удалённую или обновлённую) строку в итоговый список
        new_config_lines.append(line)

        # Если необходимо вставить дополнительные строки после firmware = "efi"
        if insert_after_firmware:
            # Добавляем board-id и hw.model, если они отсутствуют
            if not board_id_found:
                new_config_lines.append('board-id = "Mac-7BA5B2D9E42DDD94"\n')
                board_id_found = True
            if not hw_model_found:
                new_config_lines.append('hw.model = "iMacPro1,1"\n')
                hw_model_found = True
            # Добавляем board-id.reflectHost, если отсутствует
            if not board_id_reflect_found:
                new_config_lines.append('board-id.reflectHost = "FALSE"\n')
                board_id_reflect_found = True
            # Сбрасываем флаг
            insert_after_firmware = False

    # Если строки не найдены, добавляем их в конец файла
    if not serial_line_found:
        new_config_lines.append(f'serialNumber = "{new_serial_number}"\n')
    if not mac_line_found:
        new_config_lines.append(f'ethernet0.address = "{new_mac_address}"\n')
    if not uuid_bios_line_found:
        new_config_lines.append(f'uuid.bios = "{new_uuid}"\n')
    if not uuid_location_line_found:
        new_config_lines.append(f'uuid.location = "{new_uuid}"\n')
    if not rom_line_found:
        new_config_lines.append(f'efi.nvram.var.ROM = "{new_rom}"\n')
    if not mlb_line_found:
        new_config_lines.append(f'efi.nvram.var.MLB = "{new_mlb}"\n')
    if not smc_version_found:
        new_config_lines.append('smc.version = "0"\n')
    if not ethernet_address_type_found:
        new_config_lines.append('ethernet0.addressType = "static"\n')
    if not ethernet_generated_address_offset_found:
        new_config_lines.append('ethernet0.checkMACAddress = "FALSE"\n')
    if not ethernet_generated_address_found:
        new_config_lines.append(f'ethernet0.address = "{new_mac_address}"\n')
    if not hw_model_reflect_found:
        new_config_lines.append('hw.model.reflectHost = "FALSE"\n')
    if not serial_reflect_found:
        new_config_lines.append('serialNumber.reflectHost = "FALSE"\n')
    if not smbios_reflect_found:
        new_config_lines.append('smbios.reflectHost = "FALSE"\n')
    if not rom_reflect_found:
        new_config_lines.append('efi.nvram.var.ROM.reflectHost = "FALSE"\n')
    if not mlb_reflect_found:
        new_config_lines.append('efi.nvram.var.MLB.reflectHost = "FALSE"\n')
    # Добавляем board-id и hw.model, если отсутствуют и firmware = "efi" уже присутствует
    if firmware_efi_found:
        if not board_id_found:
            new_config_lines.append('board-id = "Mac-7BA5B2D9E42DDD94"\n')
        if not hw_model_found:
            new_config_lines.append('hw.model = "iMacPro1,1"\n')
        if not board_id_reflect_found:
            new_config_lines.append('board-id.reflectHost = "FALSE"\n')
    else:
        # Если firmware = "efi" отсутствует, можно добавить board-id и hw.model в конце файла
        if not board_id_found:
            new_config_lines.append('board-id = "Mac-7BA5B2D9E42DDD94"\n')
        if not hw_model_found:
            new_config_lines.append('hw.model = "iMacPro1,1"\n')
        if not board_id_reflect_found:
            new_config_lines.append('board-id.reflectHost = "FALSE"\n')

    # Дополнительная проверка для удаления любых оставшихся дубликатов с учетом регистра
    unique_config_lines = []
    seen_lines = set()
    for line in new_config_lines:
        line_lower = line.lower()
        if line_lower in seen_lines:
            continue  # Пропустить дублирующуюся строку независимо от регистра
        seen_lines.add(line_lower)
        unique_config_lines.append(line)

    with open(file_path, 'w', encoding='windows-1251') as file:
        file.writelines(unique_config_lines)

    print("Конфигурационный файл успешно обновлен.")
    print(f"Product Name: iMacPro1,1")
    print(f"Serial Number: {new_serial_number}")
    print(f"MLB: {new_mlb}")
    print(f"ROM: {new_rom}")
    print(f"MAC-адрес: {new_mac_address}")
    print(f"UUID: {new_uuid}")

if __name__ == "__main__":
    # Укажите путь к конфигурационному файлу виртуальной машины
    config_file_path = r'C:\Users\Администратор\Documents\Virtual Machines\4\4.vmx'
    update_config_file(config_file_path)
Сделай чтобы в конце удалял дубли строк