@using System.Globalization
@using CommunityToolkit.Mvvm.Messaging
@using salesbook.Shared.Components.Layout
@using salesbook.Shared.Components.Layout.Overlay
@using salesbook.Shared.Components.SingleElements.BottomSheet
@using salesbook.Shared.Core.Dto
@using salesbook.Shared.Core.Dto.Activity
@using salesbook.Shared.Core.Dto.Contact
@using salesbook.Shared.Core.Entity
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Core.Interface.IntegryApi
@using salesbook.Shared.Core.Interface.System.Network
@using salesbook.Shared.Core.Messages.Activity.Copy
@inject IManageDataService ManageData
@inject INetworkService NetworkService
@inject IIntegryApiService IntegryApiService
@inject IMessenger Messenger
@inject IDialogService Dialog
@inject IAttachedService AttachedService

<MudDialog Class="customDialog-form">
    <DialogContent>
        <HeaderLayout ShowProfile="false" Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave"
                      OnSave="Save" Title="@(IsNew ? "Nuova" : $"{ActivityModel.ActivityId}")"/>

        <div class="content">
            <div class="input-card">
                <MudTextField ReadOnly="IsView" T="string?" Placeholder="Descrizione" Variant="Variant.Text" Lines="3"
                              @bind-Value="ActivityModel.ActivityDescription" @bind-Value:after="OnAfterChangeValue"
                              DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue"/>
            </div>

            <div class="container-button">
                <MudButton Class="button-settings blue-icon"
                           FullWidth="true"
                           StartIcon="@Icons.Material.Rounded.Description"
                           Size="Size.Medium"
                           OnClick="@SuggestActivityDescription"
                           Variant="Variant.Outlined">
                    Suggerisci descrizione
                </MudButton>
            </div>

            <div class="input-card">
                <div class="form-container">
                    <MudAutocomplete ReadOnly="IsView" T="string?" Placeholder="Cliente"
                                     SearchFunc="@SearchCliente" @bind-Value="ActivityModel.Cliente"
                                     @bind-Value:after="OnClienteChanged"
                                     CoerceValue="true"/>
                </div>

                <div class="divider"></div>

                <div class="form-container">
                    <span class="disable-full-width">Commessa</span>

                    @if (ActivityModel.CodJcom != null && SelectedComessa == null)
                    {
                        <MudSkeleton/>
                    }
                    else
                    {
                        <MudAutocomplete
                            T="JtbComt?" ReadOnly="IsView"
                            @bind-Value="SelectedComessa"
                            @bind-Value:after="OnCommessaSelectedAfter"
                            SearchFunc="SearchCommesseAsync"
                            ToStringFunc="@(c => c == null ? string.Empty : $"{c.CodJcom} - {c.Descrizione}")"
                            Clearable="true"
                            OnClearButtonClick="OnCommessaClear"
                            ShowProgressIndicator="true"
                            DebounceInterval="300"
                            MaxItems="50"
                            Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code"/>
                    }
                </div>
            </div>

            <div class="input-card">
                <div class="form-container">
                    <span>Inizio</span>

                    <MudTextField ReadOnly="IsView" T="DateTime?" Format="s" Culture="CultureInfo.CurrentUICulture"
                                  InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedTime"
                                  @bind-Value:after="OnAfterChangeValue" DebounceInterval="500"
                                  OnDebounceIntervalElapsed="OnAfterChangeValue"/>
                </div>

                <div class="divider"></div>

                <div class="form-container">
                    <span>Fine</span>

                    <MudTextField ReadOnly="IsView" T="DateTime?" Format="s" Culture="CultureInfo.CurrentUICulture"
                                  InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedEndtime"
                                  @bind-Value:after="OnAfterChangeValue" DebounceInterval="500"
                                  OnDebounceIntervalElapsed="OnAfterChangeValue"/>
                </div>

                <div class="divider"></div>

                <div class="form-container">
                    <span class="disable-full-width">Avviso</span>

                    <MudSelectExtended FullWidth="true" ReadOnly="@(IsView || ActivityModel.EstimatedTime == null)"
                                       T="int" Variant="Variant.Text" @bind-Value="ActivityModel.MinuteBefore"
                                       @bind-Value:after="OnAfterChangeTimeBefore" Class="customIcon-select"
                                       AdornmentIcon="@Icons.Material.Filled.Code">
                        <MudSelectItemExtended Class="custom-item-select" Text="Nessuno" Value="-1">
                            Nessuno
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="All'ora pianificata" Value="0">All'ora
                            pianificata
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="30 minuti prima" Value="30">
                            30 minuti prima
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="1 ora prima" Value="60">
                            1 ora prima
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="2 ore prima" Value="120">
                            2 ore prima
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="1 giorno prima" Value="1440">
                            1 giorno prima
                        </MudSelectItemExtended>
                        <MudSelectItemExtended Class="custom-item-select" Text="1 settimana prima" Value="10080">
                            1 settimana prima
                        </MudSelectItemExtended>
                    </MudSelectExtended>
                </div>
            </div>

            <div class="input-card">
                <div class="form-container">
                    <span class="disable-full-width">Assegnata a</span>

                    @if (ActivityModel.UserName != null && SelectedUser == null)
                    {
                        <MudSkeleton/>
                    }
                    else
                    {
                        <MudAutocomplete
                            Disabled="Users.IsNullOrEmpty()" ReadOnly="IsView"
                            T="StbUser"
                            @bind-Value="SelectedUser"
                            @bind-Value:after="OnUserSelectedAfter"
                            SearchFunc="SearchUtentiAsync"
                            ToStringFunc="@(u => u == null ? string.Empty : u.FullName)"
                            Clearable="true"
                            OnClearButtonClick="OnUserClear"
                            ShowProgressIndicator="true"
                            DebounceInterval="300"
                            MaxItems="50"
                            Class="customIcon-select"
                            AdornmentIcon="@Icons.Material.Filled.Code"/>
                    }
                </div>

                <div class="divider"></div>

                <div class="form-container">
                    <span class="disable-full-width">Tipo</span>

                    @if (ActivityType.IsNullOrEmpty())
                    {
                        <MudSkeleton/>
                    }
                    else
                    {
                        <MudSelectExtended ReadOnly="IsView" FullWidth="true" T="string?" Variant="Variant.Text"
                                           @bind-Value="ActivityModel.ActivityTypeId"
                                           @bind-Value:after="OnAfterChangeValue" Class="customIcon-select"
                                           AdornmentIcon="@Icons.Material.Filled.Code">
                            @foreach (var type in ActivityType)
                            {
                                <MudSelectItemExtended Class="custom-item-select"
                                                       Value="@type.ActivityTypeId">@type.ActivityTypeId</MudSelectItemExtended>
                            }
                        </MudSelectExtended>
                    }
                </div>

                <div class="divider"></div>

                <div class="form-container" @onclick="OpenSelectEsito">
                    <span class="disable-full-width">Esito</span>

                    <MudSelectExtended ReadOnly="true" FullWidth="true" T="string?" Variant="Variant.Text"
                                       @bind-Value="ActivityModel.ActivityResultId"
                                       @bind-Value:after="OnAfterChangeValue" Class="customIcon-select"
                                       AdornmentIcon="@Icons.Material.Filled.Code">
                        @foreach (var result in ActivityResult)
                        {
                            <MudSelectItemExtended Class="custom-item-select"
                                                   Value="@result.ActivityResultId">@result.ActivityResultId</MudSelectItemExtended>
                        }
                    </MudSelectExtended>
                </div>
            </div>

            <div class="input-card">
                <MudTextField ReadOnly="IsView" T="string?" Placeholder="Note" Variant="Variant.Text" Lines="4"
                              @bind-Value="ActivityModel.Note" @bind-Value:after="OnAfterChangeValue"
                              DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue"/>
            </div>

            <div class="container-chip-attached">
                @if (!AttachedList.IsNullOrEmpty())
                {
                    foreach (var item in AttachedList!.Select((p, index) => new { p, index }))
                    {
                        @if (item.p.Type == AttachedDTO.TypeAttached.Position)
                        {
                            <MudChip T="string" Icon="@Icons.Material.Rounded.LocationOn" Color="Color.Success"
                                     OnClick="@(() => OpenPosition(item.p))"
                                     OnClose="@(() => OnRemoveAttached(item.index))">
                                @item.p.Description
                            </MudChip>
                        }
                        else
                        {
                            <MudChip T="string" Color="Color.Default" OnClick="@(() => OpenAttached(item.p))"
                                     OnClose="@(() => OnRemoveAttached(item.index))">
                                @item.p.Name
                            </MudChip>
                        }
                    }
                }

                @if (!IsLoading)
                {
                    if (ActivityFileList != null)
                    {
                        foreach (var file in ActivityFileList)
                        {
                            <MudChip T="string" OnClick="@(() => OpenAttached(file.Id, file.FileName))"
                                     OnClose="@(() => DeleteAttach(file))" Color="Color.Default">
                                @file.FileName
                            </MudChip>
                        }
                    }
                }
                else
                {
                    <MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="my-7"/>
                }
            </div>

            @if (!IsView)
            {
                <div class="container-button">
                    <MudButton Class="button-settings green-icon"
                               FullWidth="true"
                               StartIcon="@Icons.Material.Rounded.AttachFile"
                               Size="Size.Medium"
                               OnClick="OpenAddAttached"
                               Variant="Variant.Outlined">
                        Aggiungi allegati
                    </MudButton>

                    @if (!IsNew)
                    {
                        <div class="divider"></div>

                        <MudButton Class="button-settings gray-icon"
                                   FullWidth="true"
                                   StartIcon="@Icons.Material.Filled.ContentCopy"
                                   Size="Size.Medium"
                                   OnClick="Duplica"
                                   Variant="Variant.Outlined">
                            Duplica
                        </MudButton>

                        <div class="divider"></div>

                        <MudButton Class="button-settings red-icon"
                                   FullWidth="true"
                                   StartIcon="@Icons.Material.Outlined.Delete"
                                   Size="Size.Medium"
                                   OnClick="DeleteActivity"
                                   Variant="Variant.Outlined">
                            Elimina
                        </MudButton>
                    }
                </div>
            }
        </div>

        <MudMessageBox @ref="ConfirmDelete" Class="c-messageBox" Title="Attenzione!" CancelText="Annulla">
            <MessageContent>
                Confermi la cancellazione dell'attività corrente?
            </MessageContent>
            <YesButton>
                <MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Error"
                           StartIcon="@Icons.Material.Rounded.DeleteForever">
                    Cancella
                </MudButton>
            </YesButton>
        </MudMessageBox>
    </DialogContent>
</MudDialog>

<SaveOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation"/>

<SelectEsito @bind-IsSheetVisible="OpenEsito" @bind-ActivityModel="ActivityModel"
             @bind-ActivityModel:after="OnAfterChangeEsito"/>

<AddMemo @bind-IsSheetVisible="OpenAddMemo"/>

@code {
    [CascadingParameter] private IMudDialogInstance MudDialog { get; set; }

    [Parameter] public string? Id { get; set; }
    [Parameter] public ActivityDTO? ActivityCopied { get; set; }

    private ActivityDTO OriginalModel { get; set; } = new();
    private ActivityDTO ActivityModel { get; set; } = new();

    private List<StbActivityResult> ActivityResult { get; set; } = [];
    private List<SrlActivityTypeUser> ActivityType { get; set; } = [];
    private List<StbUser> Users { get; set; } = [];
    private List<JtbComt> Commesse { get; set; } = [];
    private List<AnagClie> Clienti { get; set; } = [];
    private List<PtbPros> Pros { get; set; } = [];
    private List<ActivityFileDto>? ActivityFileList { get; set; }

    private bool IsNew { get; set; }
    private bool IsLoading { get; set; }
    private bool IsView => !NetworkService.ConnectionAvailable;

    private string? LabelSave { get; set; }

    //Overlay for save
    private bool VisibleOverlay { get; set; }
    private bool SuccessAnimation { get; set; }

    private bool OpenEsito { get; set; }
    private bool OpenAddMemo { get; set; }

    //MessageBox
    private MudMessageBox ConfirmDelete { get; set; }

    //Attached
    private List<AttachedDTO>? AttachedList { get; set; }
    private bool CanAddPosition { get; set; } = true;

    // cache per commesse
    private string? _lastLoadedCodAnag;

    //Commessa
    private JtbComt? SelectedComessa { get; set; }

    //User
    private StbUser? SelectedUser { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;

        if (ActivityCopied != null)
        {
            ActivityModel = ActivityCopied.Clone();
        }
        else if (!Id.IsNullOrEmpty())
        {
            ActivityModel = (await ManageData.GetActivity(new WhereCondActivity { ActivityId = Id }, true)).Last();
        }

        if (Id.IsNullOrEmpty()) Id = ActivityModel.ActivityId;
        IsNew = Id.IsNullOrEmpty();
        LabelSave = IsNew ? "Aggiungi" : null;

        if (IsNew)
        {
            ActivityModel.EstimatedTime = DateTime.Today.AddHours(DateTime.Now.Hour);
            ActivityModel.EstimatedEndtime = ActivityModel.EstimatedTime?.AddHours(1);
            ActivityModel.UserName = UserSession.User.Username;
        }

        _ = LoadData();

        await LoadActivityType();
        OriginalModel = ActivityModel.Clone();
    }

    private async Task Save()
    {
        if (!CheckPreSave()) return;

        VisibleOverlay = true;
        StateHasChanged();

        await SavePosition();
        var response = await IntegryApiService.SaveActivity(ActivityModel);

        if (response == null)
            return;

        var newActivity = response.Last();
        await ManageData.InsertOrUpdate(newActivity);
        await SaveAttached(newActivity.ActivityId!);

        SuccessAnimation = true;
        StateHasChanged();

        await Task.Delay(1250);
        MudDialog.Close(newActivity);
    }

    private async Task SavePosition()
    {
        if (AttachedList is null) return;

        var positionTasks = AttachedList
            .Where(a => a.Type == AttachedDTO.TypeAttached.Position)
            .Select(async attached =>
            {
                var position = new PositionDTO
                {
                    Description = attached.Description,
                    Lat = attached.Lat,
                    Lng = attached.Lng
                };
                ActivityModel.Position = await IntegryApiService.SavePosition(position);
            });

        await Task.WhenAll(positionTasks);
    }

    private async Task SaveAttached(string activityId)
    {
        if (AttachedList is null) return;

        var uploadTasks = AttachedList
            .Where(a => a.FileContent is not null && a.Type != AttachedDTO.TypeAttached.Position)
            .Select(a => IntegryApiService.UploadFile(activityId, a.FileBytes, a.Name));

        await Task.WhenAll(uploadTasks);
    }

    private bool CheckPreSave()
    {
        Snackbar.Clear();
        if (!ActivityModel.ActivityTypeId.IsNullOrEmpty()) return true;

        Snackbar.Add("Tipo attività obbligatorio!", Severity.Error);
        return false;
    }

    private Task LoadData()
    {
        return Task.Run(async () =>
        {
            IsLoading = true;
            await InvokeAsync(StateHasChanged);

            SelectedComessa = ActivityModel.Commessa;

            Users = await ManageData.GetTable<StbUser>();
            if (!ActivityModel.UserName.IsNullOrEmpty())
            {
                SelectedUser = Users.FindLast(x => x.UserName.Equals(ActivityModel.UserName));
                await InvokeAsync(StateHasChanged);
            }

            if (!IsNew && Id != null)
                ActivityFileList = await IntegryApiService.GetActivityFile(Id);

            ActivityResult = await ManageData.GetTable<StbActivityResult>();
            Clienti = await ManageData.GetClienti(new WhereCondContact { FlagStato = "A" });
            Pros = await ManageData.GetProspect();

            IsLoading = false;
            await InvokeAsync(StateHasChanged);
        });
    }

    private async Task LoadActivityType()
    {
        if (ActivityModel.UserName is null)
        {
            ActivityType = [];
            return;
        }

        ActivityType = await ManageData.GetTable<SrlActivityTypeUser>(x => x.UserName != null && x.UserName.Equals(ActivityModel.UserName)
        );
    }

    private async Task LoadCommesse(string searchValue)
    {
        if (_lastLoadedCodAnag == ActivityModel.CodAnag && searchValue.IsNullOrEmpty()) return;

        if (ActivityModel.CodAnag == null)
        {
            Commesse = await ManageData.GetTable<JtbComt>(x =>
                x.CodJcom.ToUpper().Contains(searchValue.ToUpper()) ||
                x.Descrizione.ToUpper().Contains(searchValue.ToUpper())
            );
        }
        else
        {
            Commesse = await ManageData.GetTable<JtbComt>(x => x.CodAnag == ActivityModel.CodAnag);
        }

        Commesse = Commesse.OrderByDescending(x => x.CodJcom).ToList();
        _lastLoadedCodAnag = ActivityModel.CodAnag;
    }

    private async Task<IEnumerable<JtbComt>> SearchCommesseAsync(string value, CancellationToken token)
    {
        await LoadCommesse(value);
        if (Commesse.IsNullOrEmpty()) return [];

        IEnumerable<JtbComt> list;

        if (string.IsNullOrWhiteSpace(value))
        {
            list = Commesse.OrderByDescending(x => x.CodJcom).Take(10);
        }
        else
        {
            list = Commesse
                .Where(x => (x.CodJcom.Contains(value, StringComparison.OrdinalIgnoreCase)
                             || x.Descrizione.Contains(value, StringComparison.OrdinalIgnoreCase))
                            && (x.CodAnag == ActivityModel.CodAnag || ActivityModel.CodAnag == null))
                .OrderByDescending(x => x.CodJcom)
                .Take(50);
        }

        return token.IsCancellationRequested ? [] : list;
    }

    private Task<IEnumerable<StbUser>> SearchUtentiAsync(string value, CancellationToken token)
    {
        IEnumerable<StbUser> list;

        if (string.IsNullOrWhiteSpace(value))
        {
            list = Users.OrderBy(u => u.FullName).Take(50);
        }
        else
        {
            list = Users
                .Where(x => x.UserName.Contains(value, StringComparison.OrdinalIgnoreCase)
                            || x.FullName.Contains(value, StringComparison.OrdinalIgnoreCase))
                .OrderBy(u => u.FullName)
                .Take(50);
        }

        return Task.FromResult(token.IsCancellationRequested ? [] : list);
    }

    private Task<IEnumerable<string>?> SearchCliente(string value, CancellationToken token)
    {
        if (string.IsNullOrWhiteSpace(value))
            return Task.FromResult<IEnumerable<string>?>(null);

        var results = new List<string>();

        results.AddRange(Clienti
            .Where(x => (x.CodAnag != null && x.CodAnag.Contains(value, StringComparison.OrdinalIgnoreCase)) || x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
            .Select(x => $"{x.CodAnag} - {x.RagSoc}"));

        results.AddRange(Pros
            .Where(x => (x.CodPpro != null && x.CodPpro.Contains(value, StringComparison.OrdinalIgnoreCase)) || x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
            .Select(x => $"{x.CodPpro} - {x.RagSoc}"));

        return Task.FromResult<IEnumerable<string>?>(results);
    }

    private Task OnClienteChanged()
    {
        ActivityModel.CodJcom = null;
        if (string.IsNullOrWhiteSpace(ActivityModel.Cliente)) return Task.CompletedTask;

        var parts = ActivityModel.Cliente.Split('-', 2, StringSplitOptions.TrimEntries);
        if (parts.Length == 2)
        {
            ActivityModel.CodAnag = parts[0];
            ActivityModel.Cliente = parts[1];

            var isCliente = Clienti.FirstOrDefault(x => x.CodAnag != null && x.CodAnag.Equals(ActivityModel.CodAnag));
            ActivityModel.TipoAnag = isCliente == null ? "P" : "C";
        }

        OnAfterChangeValue();
        return Task.CompletedTask;
    }

    private void OnCommessaSelectedAfter()
    {
        var com = SelectedComessa;
        if (com != null)
        {
            ActivityModel.CodJcom = com.CodJcom;
            ActivityModel.Commessa = com;

            if (com.CodAnag != null)
            {
                ActivityModel.CodAnag = com.CodAnag;
                ActivityModel.TipoAnag = com.TipoAnag;
                ActivityModel.Cliente = Clienti
                    .Where(x => x.CodAnag != null && x.CodAnag.Equals(com.CodAnag))
                    .Select(x => x.RagSoc)
                    .FirstOrDefault() ?? Pros
                    .Where(x => x.CodPpro != null && x.CodPpro.Equals(com.CodAnag))
                    .Select(x => x.RagSoc)
                    .FirstOrDefault();
            }
            else
            {
                ActivityModel.CodAnag = null;
                ActivityModel.Cliente = null;
                ActivityModel.TipoAnag = null;
            }
        }
        else
        {
            ActivityModel.CodJcom = null;
            ActivityModel.Commessa = null;
            ActivityModel.CodAnag = null;
            ActivityModel.Cliente = null;
            ActivityModel.TipoAnag = null;
        }

        OnAfterChangeValue();
    }

    private async Task OnUserSelectedAfter()
    {
        ActivityModel.UserName = SelectedUser?.UserName;
        await LoadActivityType();
        OnAfterChangeValue();
    }

    private async Task OnCommessaClear()
    {
        ActivityModel.Commessa = null;
        ActivityModel.CodJcom = null;
        StateHasChanged();
    }

    private async Task OnUserClear()
    {
        ActivityModel.UserName = null;
        ActivityType = [];
        StateHasChanged();
    }

    private void OnAfterChangeTimeBefore()
    {
        if (ActivityModel.EstimatedTime is not null)
        {
            ActivityModel.NotificationDate = ActivityModel.MinuteBefore switch
            {
                -1 => null,
                0 => ActivityModel.EstimatedTime,
                _ => ActivityModel.EstimatedTime.Value.AddMinutes(ActivityModel.MinuteBefore * -1)
            };
        }

        OnAfterChangeValue();
    }

    private void OnAfterChangeValue()
    {
        if (!IsNew)
            LabelSave = !OriginalModel.Equals(ActivityModel) ? "Aggiorna" : null;

        if (ActivityModel.EstimatedTime is not null &&
            (ActivityModel.EstimatedEndtime is null || ActivityModel.EstimatedEndtime <= ActivityModel.EstimatedTime))
        {
            ActivityModel.EstimatedEndtime = ActivityModel.EstimatedTime.Value.AddHours(1);
        }

        StateHasChanged();
    }

    private Task OnAfterChangeEsito()
    {
        OnAfterChangeValue();
        return Task.CompletedTask;
    }

    private void OpenSelectEsito()
    {
        if (IsView) return;

        if (!IsNew && (ActivityModel.UserName is null || !ActivityModel.UserName.Equals(UserSession.User.Username)))
        {
            Snackbar.Add("Non puoi inserire un esito per un'attività che non ti è stata assegnata.", Severity.Info);
            return;
        }

        OpenEsito = !OpenEsito;
        StateHasChanged();
    }

    private async Task DeleteActivity()
    {
        var result = await ConfirmDelete.ShowAsync();

        if (result is true)
        {
            VisibleOverlay = true;
            StateHasChanged();

            try
            {
                await IntegryApiService.DeleteActivity(ActivityModel.ActivityId);
                ActivityModel.Deleted = true;

                SuccessAnimation = true;
                StateHasChanged();

                await Task.Delay(1250);

                MudDialog.Close(ActivityModel);
            }
            catch (Exception e)
            {
                VisibleOverlay = false;
                StateHasChanged();
                Snackbar.Add("Impossibile cancellare l'attività", Severity.Error);
            }
        }
    }

    private void Duplica()
    {
        var activityCopy = ActivityModel.Clone();
        activityCopy.ActivityId = null;

        MudDialog.Cancel();
        Messenger.Send(new CopyActivityMessage(activityCopy));
    }

    private async Task OpenAddAttached()
    {
        var result = await ModalHelpers.OpenAddAttached(Dialog, CanAddPosition);

        if (result is { Canceled: false, Data: not null } && result.Data.GetType() == typeof(AttachedDTO))
        {
            var attached = (AttachedDTO)result.Data;

            if (attached.Type == AttachedDTO.TypeAttached.Position)
                CanAddPosition = false;

            AttachedList ??= [];
            AttachedList.Add(attached);

            LabelSave = "Aggiorna";
        }
    }

    private void OnRemoveAttached(int index)
    {
        if (AttachedList is null || index < 0 || index >= AttachedList.Count)
            return;

        var attached = AttachedList[index];

        if (attached.Type == AttachedDTO.TypeAttached.Position)
            CanAddPosition = true;

        AttachedList.RemoveAt(index);
        StateHasChanged();
    }

    private async Task OpenAttached(string idAttached, string fileName)
    {
        try
        {
            var bytes = await IntegryApiService.DownloadFile(ActivityModel.ActivityId!, fileName);
            await AttachedService.OpenFile(bytes, fileName);
        }
        catch (Exception ex)
        {
            Snackbar.Clear();
            Snackbar.Add("Impossibile aprire il file", Severity.Error);
            Console.WriteLine($"Errore durante l'apertura del file: {ex.Message}");
        }
    }

    private async Task OpenAttached(AttachedDTO attached)
    {
        if (attached is { FileContent: not null, MimeType: not null })
        {
            await AttachedService.OpenFile(attached.FileContent!, attached.Name);
        }
        else
        {
            Snackbar.Clear();
            Snackbar.Add("Impossibile aprire il file", Severity.Error);
        }
    }

    private async Task DeleteAttach(ActivityFileDto file)
    {
        Snackbar.Clear();

        if (ActivityFileList == null) return;

        try
        {
            ActivityFileList.Remove(file);
            StateHasChanged();

            await IntegryApiService.DeleteFile(ActivityModel.ActivityId!, file.FileName);
        }
        catch (Exception ex)
        {
            ActivityFileList.Add(file);
            StateHasChanged();

            Snackbar.Add("Impossibile eliminare il file", Severity.Error);
            Console.WriteLine($"Impossibile eliminare il file: {ex.Message}");
        }
        finally
        {
            Snackbar.Add($"{file.FileName} eliminato con successo", Severity.Info);
        }
    }

    private void OpenPosition(AttachedDTO attached)
    {
        if (attached is { Lat: not null, Lng: not null })
        {
            const string baseUrl = "https://www.google.it/maps/place/";
            NavigationManager.NavigateTo(
                $"{baseUrl}{AdjustCoordinate(attached.Lat.Value)},{AdjustCoordinate(attached.Lng.Value)}"
            );
        }
        else
        {
            Snackbar.Clear();
            Snackbar.Add("Impossibile aprire la posizione", Severity.Error);
        }
    }

    private static string AdjustCoordinate(double coordinate) =>
        coordinate.ToString(CultureInfo.InvariantCulture).Replace(",", ".");

    private async Task SuggestActivityDescription()
    {
        if (ActivityModel.ActivityTypeId == null)
        {
            Snackbar.Add("Indicare prima il tipo attività", Severity.Error);
            return;
        }

        VisibleOverlay = true;
        StateHasChanged();

        _ = Task.Run(async () =>
        {
            var activityDescriptions = await IntegryApiService.SuggestActivityDescription(ActivityModel.ActivityTypeId);

            var modal = ModalHelpers.OpenSuggestActivityDescription(Dialog, activityDescriptions);

            if (modal is { IsCanceled: false, Result: not null })
                ActivityModel.ActivityDescription = modal.Result.Data!.ToString();

            VisibleOverlay = false;
            await InvokeAsync(StateHasChanged);
        });
    }

}