from lavalink import LoadType
import re


async def add_song_recommendations(
    openai_client, bot_user, player, number, inputs, retries: int = 1
):
    input_list = [f'"{song} by {artist}"' for song, artist in inputs.items()]

    completion = (
        openai_client.chat.completions.create(
            messages=[
                {
                    "role": "user",
                    "content": f"""
                        BACKGROUND: You're an AI music recommendation system with a knack for understanding
                        user preferences based on provided input. Your task is to generate a list
                        of {number} songs that the user might enjoy, derived from a given list of {number} songs.
                        The input will be in the format of
                            ["Song-1-Name by Song-1-Artist", "Song-2-Name by Song-2-Artist", ...]
                        and you need to return a list formatted in the same way.

                        When recommending songs, consider the genre, tempo, and mood of the input
                        songs to suggest similar ones that align with the user's tastes. Also, it
                        is important to mix up the artists, don't only give the same artists that
                        are already in the queue. If you cannot find {number} songs that match the
                        criteria or encounter any issues, return the list ["NOTHING FOUND"].

                        Please be sure to also only use characters A-Z, a-z, 0-9, and spaces in the
                        song and artist names. Do not include escape/special characters, emojis, or
                        quotes in the output.

                        INPUT: {input_list}
                    """,
                }
            ],
            model="gpt-4o-mini",
        )
        .choices[0]
        .message.content.strip()
        .strip('"')
    )

    # Sometimes ChatGPT will return `["NOTHING FOUND"]` even if it should
    # have found something, so we check each prompt up to 3 times before
    # giving up.
    if completion == '["NOTHING FOUND"]':
        if retries <= 3:
            await add_song_recommendations(
                openai_client, bot_user, player, number, inputs, retries + 1
            )
        else:
            return False

    else:
        # Clean up the completion string to remove any potential issues
        # with the eval function (e.g. OUTPUT: prefix, escaped quotes, etc.)
        completion = re.sub(r"[\\\'\[\]\n]+|OUTPUT: ", "", completion)

        for entry in eval(completion):
            song, artist = entry.split(" by ")
            ytsearch = f"ytsearch:{song} by {artist} audio"
            results = await player.node.get_tracks(ytsearch)

            if not results.tracks or results.load_type in (
                LoadType.EMPTY,
                LoadType.ERROR,
            ):
                dzsearch = f"dzsearch:{song}"
                results = await player.node.get_tracks(dzsearch)

                if not results.tracks or results.load_type in (
                    LoadType.EMPTY,
                    LoadType.ERROR,
                ):
                    continue

            track = results.tracks[0]
            player.add(requester=bot_user, track=track)

        return True