"""
Module for creating m3u content and writing it to a file.
"""

from pathlib import Path
from typing import Dict, List, Optional

from spotdl.types.song import Song
from spotdl.utils.formatter import create_file_name, sanitize_string

__all__ = [
    "create_m3u_content",
    "gen_m3u_files",
    "create_m3u_file",
]


def create_m3u_content(
    song_list: List[Song],
    template: str,
    file_extension: str,
    restrict: Optional[str] = None,
    short: bool = False,
    detect_formats: Optional[List[str]] = None,
) -> str:
    """
    Create m3u content and return it as a string.

    ### Arguments
    - song_list: the list of songs
    - template: the template to use
    - file_extension: the file extension to use
    - restrict: sanitization to apply to the filename
    - short: whether to use the short version of the template
    - detect_formats: the formats to detect for existing files

    ### Returns
    - the m3u content as a string
    """

    text = "#EXTM3U\n"

    for song in song_list:
        metadata = create_file_name(
            song, "#EXTINF:{duration},{album-artist} - {title}", ""
        )
        text += str(metadata) + "\n"

        if not detect_formats:
            file_name = create_file_name(
                song, template, file_extension, restrict, short
            )

            text += str(file_name) + "\n"
        else:
            for file_ext in detect_formats:
                file_name = create_file_name(song, template, file_ext, restrict, short)

                if file_name.exists():
                    text += str(file_name) + "\n"
                    break

                file_name = create_file_name(
                    song, template, file_extension, restrict, short
                )
                text += str(file_name) + "\n"

    return text


def gen_m3u_files(
    songs: List[Song],
    file_name: Optional[str],
    template: str,
    file_extension: str,
    restrict: Optional[str] = None,
    short: bool = False,
    detect_formats: Optional[List[str]] = None,
):
    """
    Create an m3u8 filename from the query.

    ### Arguments
    - songs: the list of songs
    - file_name: the file name to use
    - template: the output file template to use
    - file_extension: the file extension to use
    - restrict: sanitization to apply to the filename
    - short: whether to use the short version of the template
    - detect_formats: the formats to detect
    """

    # If no file name is provided, use the first list's name
    if not file_name:
        file_name = "{list[0]}.m3u8"

    # If file_name ends with a slash. Does not have a m3u8 name with extension
    # at the end of the template, append `{list[0]}`` to it
    if (
        file_name.endswith("/")
        or file_name.endswith(r"\\")
        or file_name.endswith("\\\\")
    ):
        file_name += "/{list[0]}.m3u8"

    # Check if the file name ends with .m3u or .m3u8
    if not file_name.endswith(".m3u") and not file_name.endswith(".m3u8"):
        file_name += ".m3u8"

    lists_object: Dict[str, List[Song]] = {}
    for song in songs:
        if song.list_name is None:
            continue

        if song.list_name not in lists_object:
            lists_object[song.list_name] = []

        lists_object[song.list_name].append(song)

    if "{list}" in file_name:
        # Create multiple m3u files if there are multiple lists
        for list_name, song_list in lists_object.items():
            create_m3u_file(
                file_name.format(
                    list=list_name,
                ),
                song_list,
                template,
                file_extension,
                restrict,
                short,
                detect_formats,
            )
    elif "{list[" in file_name and "]}" in file_name:
        # Create a single m3u file for specified song list name
        create_m3u_file(
            file_name.format(list=list(lists_object.keys())),
            songs,
            template,
            file_extension,
            restrict,
            short,
            detect_formats,
        )
    else:
        # Use the provided file name
        create_m3u_file(
            file_name,
            songs,
            template,
            file_extension,
            restrict,
            short,
            detect_formats,
        )


def create_m3u_file(
    file_name: str,
    song_list: List[Song],
    template: str,
    file_extension: str,
    restrict: Optional[str] = None,
    short: bool = False,
    detect_formats: Optional[List[str]] = None,
) -> str:
    """
    Create the m3u file.

    ### Arguments
    - file_name: the file name to use
    - song_list: the list of songs
    - template: the template to use
    - file_extension: the file extension to use
    - restrict: sanitization to apply to the filename
    - short: whether to use the short version of the template
    - detect_formats: the formats to detect

    ### Returns
    - the m3u content as a string
    """

    m3u_content = create_m3u_content(
        song_list,
        template,
        file_extension,
        restrict,
        short,
        detect_formats,
    )

    file_path = Path(
        *(sanitize_string(part) for part in Path(file_name).parts)
    ).absolute()

    with open(file_path, "w", encoding="utf-8") as m3u_file:
        m3u_file.write(m3u_content)

    return m3u_content
