import sys
import yaml
from copy import deepcopy
from collections.abc import Mapping

def ensure_list(val):
    if val is None:
        return []
    if isinstance(val, list):
        return val
    return [val]

def merge_named_lists(list1, list2, key_name="name"):
    if not all(isinstance(i, dict) for i in list1 + list2):
        return list1 + list2  # fallback: just concatenate

    merged_dict = {item.get(key_name): deepcopy(item) for item in list1 if key_name in item}
    result = [deepcopy(item) for item in list1 if key_name not in item]  # items without key

    for item in list2:
        item_key = item.get(key_name)
        if item_key and item_key in merged_dict:
            merged_dict[item_key] = deep_merge(merged_dict[item_key], item)
        elif item_key:
            merged_dict[item_key] = deepcopy(item)
        else:
            result.append(deepcopy(item))

    return list(merged_dict.values()) + result

def merge_appenders(app1, app2):
    merged = deepcopy(app1)
    for appender_type, value2 in app2.items():
        value1 = merged.get(appender_type)
        list1 = ensure_list(value1)
        list2 = ensure_list(value2)
        merged[appender_type] = merge_named_lists(list1, list2, key_name="name")
    return merged

def deep_merge(dict1, dict2):
    result = deepcopy(dict1)
    for key, value in dict2.items():
        if key in result:
            # Special handling for Appenders and similar sections
            if key == "Appenders" and isinstance(result[key], dict) and isinstance(value, dict):
                result[key] = merge_appenders(result[key], value)
            elif isinstance(result[key], Mapping) and isinstance(value, Mapping):
                result[key] = deep_merge(result[key], value)
            elif isinstance(result[key], list) and isinstance(value, list):
                list_key = "ref" if key == "AppenderRef" else "name"
                result[key] = merge_named_lists(result[key], value, key_name=list_key)
            else:
                result[key] = deepcopy(value)
        else:
            result[key] = deepcopy(value)
    return result

def merge_log4j2_yaml(file1_path, file2_path, output_path):
    with open(file1_path, 'r') as f1, open(file2_path, 'r') as f2:
        yaml1 = yaml.safe_load(f1)
        yaml2 = yaml.safe_load(f2)

    merged = deep_merge(yaml1, yaml2)

    with open(output_path, 'w') as out:
        yaml.dump(merged, out, default_flow_style=False, sort_keys=False)

    return merged

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python merge_log4j2_yaml.py <base.yaml> <override.yaml> <output.yaml>")
        sys.exit(1)
    base_file = sys.argv[1]
    override_file = sys.argv[2]
    output_file = sys.argv[3]
    merge_log4j2_yaml(base_file, override_file, output_file)
    print(f"Merged YAML written to {output_file}")
