using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using ASTRAIN.Shared.Dtos;
using ASTRAIN.Shared.Requests;

namespace ASTRAIN.Client.Pages;

public partial class Exercises
{
    /// <summary>
    /// Optional user id from route.
    /// </summary>
    [Parameter]
    public string? UserId { get; set; }

    /// <summary>
    /// The list of exercises for the current user.
    /// </summary>
    private List<ExerciseDto> ExerciseList { get; set; } = new();

    /// <summary>
    /// Whether the page is currently loading data.
    /// </summary>
    private bool IsLoading { get; set; } = true;

    /// <summary>
    /// Whether the create exercise UI is visible.
    /// </summary>
    private bool ShowCreateExercise { get; set; }

    /// <summary>
    /// Name for a new exercise being created.
    /// </summary>
    private string NewExerciseName { get; set; } = string.Empty;

    /// <summary>
    /// The currently edited exercise id, if any.
    /// </summary>
    private int? EditingId { get; set; }

    /// <summary>
    /// The current edited exercise name.
    /// </summary>
    private string EditingName { get; set; } = string.Empty;

    /// <inheritdoc/>
    protected override async Task OnInitializedAsync()
    {
        var ensured = await Api.EnsureUserAsync(UserId);
        if (string.IsNullOrWhiteSpace(ensured))
        {
            return;
        }

        UserContext.SetUserId(ensured);
        if (UserId != ensured)
        {
            Navigation.NavigateTo($"/{ensured}/exercises", true);
            return;
        }

        await LoadExercisesAsync();
    }

    /// <summary>
    /// Loads exercises from the API.
    /// </summary>
    private async Task LoadExercisesAsync()
    {
        IsLoading = true;
        ExerciseList = await Api.GetExercisesAsync(UserContext.UserId);
        IsLoading = false;
    }

    /// <summary>
    /// Creates a new exercise with the provided name.
    /// </summary>
    private async Task CreateExerciseAsync()
    {
        if (string.IsNullOrWhiteSpace(NewExerciseName))
        {
            return;
        }

        var result = await Api.CreateExerciseAsync(UserContext.UserId, new ExerciseUpsertRequest(NewExerciseName));
        if (result is not null)
        {
            ExerciseList.Add(result);
            ExerciseList = ExerciseList.OrderBy(e => e.Name).ToList();
            NewExerciseName = string.Empty;
        }
    }

    /// <summary>
    /// Toggles the create form visibility.
    /// </summary>
    private void ToggleCreate()
    {
        ShowCreateExercise = !ShowCreateExercise;
    }

    /// <summary>
    /// Begin editing the supplied exercise.
    /// </summary>
    private void StartEdit(ExerciseDto exercise)
    {
        EditingId = exercise.Id;
        EditingName = exercise.Name;
    }

    /// <summary>
    /// Cancel the current edit.
    /// </summary>
    private void CancelEdit()
    {
        EditingId = null;
        EditingName = string.Empty;
    }

    /// <summary>
    /// Save the edited exercise name.
    /// </summary>
    private async Task SaveEditAsync(int exerciseId)
    {
        if (string.IsNullOrWhiteSpace(EditingName))
        {
            return;
        }

        var result = await Api.UpdateExerciseAsync(UserContext.UserId, exerciseId, new ExerciseUpsertRequest(EditingName));
        if (result is not null)
        {
            var index = ExerciseList.FindIndex(e => e.Id == exerciseId);
            if (index >= 0)
            {
                ExerciseList[index] = result;
                ExerciseList = ExerciseList.OrderBy(e => e.Name).ToList();
            }
        }

        CancelEdit();
    }

    /// <summary>
    /// Deletes the exercise with the given id after confirmation.
    /// </summary>
    private async Task DeleteExerciseAsync(int exerciseId)
    {
        var confirmed = await JS.InvokeAsync<bool>("confirm", "Are you sure you want to delete this exercise?");
        if (!confirmed) return;

        await Api.DeleteExerciseAsync(UserContext.UserId, exerciseId);
        ExerciseList.RemoveAll(e => e.Id == exerciseId);
    }
}
