using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualBasic;

namespace sotd.Pages;

public class SongSubmissionModel : PageModel
{
    private readonly ILogger<UserModel> _logger;

    private SongResolver songResolver;

    private string _submitUrl;

    private SpotifyApiClient spotifyApiClient;

    private SignalIntegration signalIntegration;

    public SongSubmissionModel(ILogger<UserModel> logger, SongResolver songResolver, SpotifyApiClient spotifyApiClient, SignalIntegration signalIntegration)
    {
        _logger = logger;
        this.spotifyApiClient = spotifyApiClient;
        this.songResolver = songResolver;
        this.signalIntegration = signalIntegration;
        _submitUrl = string.Empty;
        SongData = new Song();
    }

    [Parameter]
    public int? SubmissionIndex { get; set; }

    [BindProperty]
    public bool IsValidUrl { get; set; } = true;

    [BindProperty]
    public bool IsPageReadonly { get; set; } = false;

    [BindProperty]
    public SuggestionHelper? SuggestionHelper { get; set; } = null;

    [BindProperty]
    public List<SongSuggestion> UserSongSubmissions { get; set; } = [];

    [BindProperty(SupportsGet = true)]
    public string SubmitUrl
    {
        get
        {
            return _submitUrl;
        }
        set
        {
            _submitUrl = value == null ? string.Empty : value.ToString();
            Uri? newValue = default;
            try
            {
                newValue = new Uri(_submitUrl);
            }
            catch (UriFormatException)
            {
                IsValidUrl = false;
                return;
            }

            IsValidUrl = true;

            if (this.songResolver.CanValidate(newValue))
            {
                this.SongData = this.songResolver.ResolveSongAsync(newValue).Result;
            }
        }
    }


    public List<SpotifyAPI.Web.FullTrack> SpotifySuggestions
    {
        get
        {
            var suggestionList = new List<SpotifyAPI.Web.FullTrack>();
            if (!string.IsNullOrEmpty(this.SongData.Name) && !string.IsNullOrEmpty(this.SongData.Artist))
            {
                suggestionList.AddRange(spotifyApiClient.GetTrackCandidatesAsync(this.SongData.Name, this.SongData.Artist).Result);
            }
            return suggestionList;
        }
    }

    public IActionResult OnGetSpotifySuggestions(string song, string artist, string submitUrl, SongProvider provider, string spotifyId)
    {
        this.SongData.Name = song;
        this.SongData.Artist = artist;
        this.SongData.Url = submitUrl;
        this.SongData.Provider = provider;
        this.SongData.SpotifyId = spotifyId;
        return Partial("_SpotifySongSuggestionsPartial", this.SpotifySuggestions);
    }

    [BindProperty]
    public string CanSubmit
    {
        get
        {
            var disableCondition = !(string.IsNullOrEmpty(SongData?.Artist) && string.IsNullOrEmpty(SongData?.Name));
            return disableCondition ? "" : "disabled";
        }
    }

    [BindProperty(SupportsGet = true)]
    public Song SongData { get; set; }

    [BindProperty(SupportsGet = true)]
    public bool HasUsedSuggestion { get; set; } = true;

    private async Task UpdateGroup(SongSuggestion suggestion)
    {
        var isItToday = suggestion.Date.Date == DateTime.Today;
        var dateString = isItToday ? "submission for today" : "submission from " + suggestion.Date.ToString("dd. MM. yyyy");
        var displayName = string.IsNullOrEmpty(suggestion.User.NickName) ? suggestion.User.Name : suggestion.User.NickName;
        var imageBuilder = await songResolver.GetPreviewImageAsync(suggestion.Song.SpotifyId);
        var previewData = new LinkPreviewAttachment()
        {
            Title = suggestion.Song.Name,
            Description = suggestion.Song.Artist,
            Url = suggestion.Song.Url,
            Base64Image = imageBuilder.ToString(),
        };
        await signalIntegration.SendMessageToGroupAsync($"**{displayName}**'s " + dateString + $" is: \n\n {suggestion.Song.Url}", previewData);
        if (suggestion.HasUsedSuggestion)
        {
            await signalIntegration.SendMessageToGroupAsync($"The suggestion used for this pick was: \n\n **{suggestion.SuggestionHelper.Title}**'s \n\n {suggestion.SuggestionHelper.Description}");
        }
    }

    public async Task<IActionResult> OnPost(int? submissionIndex)
    {
        if (submissionIndex == null)
        {
            throw new Exception("Attempt to submit song without submissionId");
        }
        // Todo implement save submission
        using var dci = DataContext.Instance;
        var suggestion = dci.SongSuggestions
                .Include(s => s.User)
                .Include(s => s.SuggestionHelper)
                .Where(s => s.Id == submissionIndex)
                .FirstOrDefault();

        if (suggestion == null)
        {
            throw new Exception("Attempt to submit song with invalid submissionId");
        }

        this.SongData.Artist = Request.Form["Artist"];
        this.SongData.Url = Request.Form["SubmitUrl"];
        this.SongData.Name = Request.Form["Name"];
        this.SongData.SpotifyId = Request.Form["SpotifyId"];
        this.SongData.Provider = Enum.Parse<SongProvider>(Request.Form["Provider"]);

        // Let's check if we already have this song in the DB
        var songToUse = dci.Songs.Where(s => s.SpotifyId == this.SongData.SpotifyId).FirstOrDefault();
        if (songToUse == null)
        {
            // Song was not in DB yet, creating a new one
            var newSong = new Song()
            {
                SpotifyId = this.SongData.SpotifyId,
                Artist = this.SongData.Artist,
                Name = this.SongData.Name,
                Url = this.SongData.Url,
                Provider = this.SongData.Provider,
            };
            var dbRecord = dci.Songs.Add(newSong);
            var newId = await dci.SaveChangesAsync();
            songToUse = dbRecord.Entity;
        }
        suggestion.Song = songToUse;
        suggestion.UserHasSubmitted = true;
        suggestion.HasUsedSuggestion = this.HasUsedSuggestion;
        dci.Update(suggestion);
        await dci.SaveChangesAsync();
        // load overview page again after submitting

        await UpdateGroup(suggestion);

        return RedirectToPage("SongSubmission");
    }

    public void OnGet(int? submissionIndex)
    {
        this.SubmissionIndex = submissionIndex;

        // we want to show overview, so we need to fetch user submission list
        if (submissionIndex == null)
        {
            using var dci = DataContext.Instance;
            var currentUserName = this.User.Identity.Name;
            this.UserSongSubmissions = dci.SongSuggestions
                            .Include(s => s.SuggestionHelper)
                            .Include(s => s.Song)
                            .Where(s => s.User.LdapUserName.Equals(currentUserName))
                            .OrderByDescending(s => s.Date)
                            .ToList();
        }
        else
        {
            using var dci = DataContext.Instance;
            var songSuggestion = dci.SongSuggestions
                            .Include(s => s.SuggestionHelper)
                            .Include(s => s.Song)
                            .Where(s => s.Id.Equals(submissionIndex.Value))
                            .First();
            this.SuggestionHelper = songSuggestion.SuggestionHelper;
            this.SongData = songSuggestion.Song == null ? new Song() : songSuggestion.Song;
            this.SubmitUrl = this.SongData.Url;
            if (!string.IsNullOrEmpty(this.SongData.Name) && !string.IsNullOrEmpty(this.SongData.Artist))
            {
                this.IsPageReadonly = true;
            }
        }
    }

    public IActionResult OnGetUpdate()
    {
        var songUrl = Request.Query["SubmitUrl"];
        this.SubmitUrl = songUrl.ToString();
        var songPartialModel = new SongPartialModel()
        {
            InnerSong = SongData,
            IsPageReadonly = false
        };
        return Partial("_SongPartial", songPartialModel); ;
    }
}
