import unreal


SOURCE_CHARACTER = "/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter"
SOURCE_CONTROLLER = "/Game/ThirdPerson/Blueprints/BP_ThirdPersonPlayerController"
SOURCE_GAME_MODE = "/Game/ThirdPerson/Blueprints/BP_ThirdPersonGameMode"

DEST_ROOT = "/Game/Agrarian/Blueprints/Characters"
DEST_CHARACTER = f"{DEST_ROOT}/BP_AgrarianPlayerCharacter"
DEST_CONTROLLER = f"{DEST_ROOT}/BP_AgrarianPlayerController"
DEST_GAME_MODE = f"{DEST_ROOT}/BP_AgrarianGameMode"

KNOWN_RECIPE_ASSETS = [
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_Campfire",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_PrimitiveFrame",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_PrimitiveWallPanel",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_PrimitiveRoofPanel",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_PrimitiveShelter",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_BasicTool",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_SimpleContainer",
    "/Game/Agrarian/DataAssets/Recipes/DA_Recipe_Bandage",
]


def ensure_directory(path):
    if not unreal.EditorAssetLibrary.does_directory_exist(path):
        if not unreal.EditorAssetLibrary.make_directory(path):
            raise RuntimeError(f"Could not create content directory: {path}")


def duplicate_if_missing(source_path, destination_path):
    if unreal.EditorAssetLibrary.does_asset_exist(destination_path):
        unreal.log(f"Keeping existing asset: {destination_path}")
        return unreal.EditorAssetLibrary.load_asset(destination_path)

    if not unreal.EditorAssetLibrary.does_asset_exist(source_path):
        raise RuntimeError(f"Source asset missing: {source_path}")

    duplicated = unreal.EditorAssetLibrary.duplicate_asset(source_path, destination_path)
    if not duplicated:
        raise RuntimeError(f"Could not duplicate {source_path} to {destination_path}")

    unreal.log(f"Created {destination_path} from {source_path}")
    return duplicated


def load_blueprint_class(path):
    generated_class = unreal.EditorAssetLibrary.load_blueprint_class(path)
    if not generated_class:
        raise RuntimeError(f"Could not load generated Blueprint class: {path}")
    return generated_class


def load_required_asset(path):
    asset = unreal.EditorAssetLibrary.load_asset(path)
    if not asset:
        raise RuntimeError(f"Required asset not found: {path}")
    return asset


def main():
    ensure_directory(DEST_ROOT)

    character_bp = duplicate_if_missing(SOURCE_CHARACTER, DEST_CHARACTER)
    controller_bp = duplicate_if_missing(SOURCE_CONTROLLER, DEST_CONTROLLER)
    game_mode_bp = duplicate_if_missing(SOURCE_GAME_MODE, DEST_GAME_MODE)

    character_class = load_blueprint_class(DEST_CHARACTER)
    controller_class = load_blueprint_class(DEST_CONTROLLER)
    character_cdo = unreal.get_default_object(character_class)
    game_mode_cdo = unreal.get_default_object(game_mode_bp.generated_class())

    game_mode_cdo.set_editor_property("default_pawn_class", character_class)
    game_mode_cdo.set_editor_property("player_controller_class", controller_class)

    crafting_component = character_cdo.get_editor_property("crafting_component")
    if not crafting_component:
        raise RuntimeError("BP_AgrarianPlayerCharacter is missing CraftingComponent")
    crafting_component.set_editor_property(
        "known_recipe_assets",
        [load_required_asset(path) for path in KNOWN_RECIPE_ASSETS],
    )

    unreal.BlueprintEditorLibrary.compile_blueprint(character_bp)
    unreal.EditorAssetLibrary.save_loaded_asset(character_bp)
    unreal.EditorAssetLibrary.save_loaded_asset(controller_bp)
    unreal.EditorAssetLibrary.save_loaded_asset(game_mode_bp)

    unreal.log(
        "Agrarian player Blueprint assets are ready: "
        f"{DEST_CHARACTER}, {DEST_CONTROLLER}, {DEST_GAME_MODE}"
    )


main()
