using MetaBrainz.MusicBrainz;
using MetaBrainz.MusicBrainz.Interfaces.Entities;
using TagLib;
using UniversalTagEditor.Types;

public static class TagEditor {
    public static void Edit(string filePath, AlbumInfo info, int trackNum)
    {
        TagLib.File file = TagLib.File.Create(filePath);

        if (info.Name != null)
            file.Tag.Album = info.Name;
        
        if (info.Cover != null)
        {
            Picture picture = new Picture(info.Cover);
            picture.Type = PictureType.FrontCover;
            file.Tag.Pictures = new[] { picture };
        }

        if (info.Tracks.Length > 0)
        {
            file.Tag.Title = info.Tracks[trackNum].Title;
            file.Tag.Track = uint.Parse(info.Tracks[trackNum].TrackNumber);
            file.Tag.Year = uint.Parse(info.Tracks[trackNum].Year);
            file.Tag.Composers = info.Tracks[trackNum].Composers.Split(";");
            file.Tag.Disc = uint.Parse(info.Tracks[trackNum].Disc);
            file.Tag.Performers = info.Tracks[trackNum].Artists.Split(";");
            file.Tag.AlbumArtists = new List<string>(["Microsoft"]).ToArray();
            file.Tag.Genres = info.Tracks[trackNum].Genres.Split(";");
            file.Tag.Publisher = info.Tracks[trackNum].Publisher;
        }

        file.Save();
    }

    public static async Task Fix(string filePath, Query query, bool enhanceStructure, string format)
    {
        TagLib.File file = TagLib.File.Create(filePath);

        if (file.Tag.Performers.Length == 1) {
            List<string> performers = file.Tag.Performers[0]
                                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
                                        .SelectMany(p => p.Split('&', StringSplitOptions.RemoveEmptyEntries))
                                        .Select(p => p.Trim())
                                        .Where(p => p.Length > 0)
                                        .ToList();

            file.Tag.Performers = performers.ToArray();
            if (file.Tag.AlbumArtists == null || file.Tag.AlbumArtists.Length == 0)
                file.Tag.AlbumArtists = new [] { performers[0] };
            else
            {
                List<string> albumArtist = file.Tag.AlbumArtists[0]
                                    .Split(',', StringSplitOptions.RemoveEmptyEntries)
                                    .SelectMany(p => p.Split('&', StringSplitOptions.RemoveEmptyEntries))
                                    .Select(p => p.Trim())
                                    .Where(p => p.Length > 0)
                                    .ToList();
                file.Tag.AlbumArtists = albumArtist.ToArray();
            }
        }

        if (file.Tag.Genres == null || file.Tag.Genres.Length == 0)
        {
            bool noException = false;

            while (!noException)
            {
                try
                {
                    var albumSearch = await query.FindReleaseGroupsAsync($"artist:\"{file.Tag.AlbumArtists[0]}\" AND releasegroup:\"{file.Tag.Album}\"");
                    var albumResult = albumSearch.Results.FirstOrDefault()?.Item;

                    if (albumResult != null)
                    {
                        IReleaseGroup fullAlbum = await query.LookupReleaseGroupAsync(albumResult.Id, Include.Genres);
                        file.Tag.Genres = fullAlbum.Genres?.Select(g => 
                                string.Join(" ", g.Name.Split(" ").Select(n => n[0].ToString().ToUpper() + n[1..^0]))
                            ).ToArray();
                    }
                }
                catch { }
                finally
                {
                    noException = true;
                }
            }
        }

        file.Save();

        if (enhanceStructure)
        {
            FileInfo path = new FileInfo(filePath);
            Console.WriteLine(file.Tag.Album);
            string album = file.Tag.Year + " — " + ReplaceSystemSymbols(file.Tag.Album);
            if (!Directory.Exists(Path.Combine(path.DirectoryName!, album)))
                Directory.CreateDirectory(Path.Combine(path.DirectoryName!, album));
            
            string output = Path.Combine(path.DirectoryName!, 
                        album, 
                        $"{file.Tag.Track}. {string.Join(", ", file.Tag.Performers.Select(p => ReplaceSystemSymbols(p)))} - {ReplaceSystemSymbols(file.Tag.Title)}.{format}");

            if (System.IO.File.Exists(output))
                System.IO.File.Delete(filePath);
            else
                System.IO.File.Move(filePath, output);
            await Task.Delay(500);
        }
    }

    private static string ReplaceSystemSymbols(string origin)
    {
        string result = origin;

        if (result.Contains("/"))
            result = result.Replace("/", "-");
        if (result.Contains(":"))
            result = result.Replace(":", "-");
        if (result.Contains("|"))
            result = result.Replace("|", "-");
        if (result.Contains("\\"))
            result = result.Replace("\\", "-");
        if (result.Contains("?"))
            result = result.Replace("?", "");
        if (result.Contains("\""))
            result = result.Replace("\"", "_");
        if (result.Contains("*"))
            result = result.Replace("*", "_");
        if (result.Contains("<"))
            result = result.Replace("<", "_");
        if (result.Contains(">"))
            result = result.Replace(">", "_");

        return result;
    }
}