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

<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="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 (Commesse.IsNullOrEmpty())
                    {
                        <span class="warning-text">Nessuna commessa presente</span>
                    }
                    else
                    {
                        <MudSelectExtended FullWidth="true" ReadOnly="@(IsView || Commesse.IsNullOrEmpty())" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.CodJcom" @bind-Value:after="OnCommessaChanged" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
                            @foreach (var com in Commesse)
                            {
                                <MudSelectItemExtended Class="custom-item-select" Value="@com.CodJcom">@($"{com.CodJcom} - {com.Descrizione}")</MudSelectItemExtended>
                            }
                        </MudSelectExtended>
                    }
                </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>Avviso</span>

                    <MudSwitch ReadOnly="IsView" T="bool" Disabled="true" Color="Color.Primary"/>
                </div>
            </div>

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

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

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

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

                    <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 (ActivityFileList != null)
                {
                    foreach (var file in ActivityFileList)
                    {
                        <MudChip T="string" Color="Color.Default">
                            @file.FileName
                        </MudChip>
                    }
                }
            </div>

            <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>
        
        <MudMessageBox @ref="AddNamePosition" Class="c-messageBox" Title="Nome della posizione" CancelText="Annulla">
            <MessageContent>
                <MudTextField @bind-Value="NamePosition" Variant="Variant.Outlined" />
            </MessageContent>
            <YesButton>
                <MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary"
                           StartIcon="@Icons.Material.Rounded.Check">
                    Salva
                </MudButton>
            </YesButton>
        </MudMessageBox>

        <MudMessageBox @ref="ConfirmMemo" Class="c-messageBox" Title="Attenzione!" CancelText="Annulla">
            <MessageContent>
                Vuoi creare un promemoria?
            </MessageContent>
            <YesButton>
                <MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary"
                           StartIcon="@Icons.Material.Rounded.Check">
                    Crea
                </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<StbActivityType> 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 => Id.IsNullOrEmpty();
    private bool IsView => !NetworkService.IsNetworkAvailable();

    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; }
    private MudMessageBox ConfirmMemo { get; set; }
    private MudMessageBox AddNamePosition { get; set; }

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

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

        _ = LoadData();

        LabelSave = IsNew ? "Aggiungi" : null;

        if (!Id.IsNullOrEmpty())
            ActivityModel = (await ManageData.GetActivity(x => x.ActivityId.Equals(Id))).Last();

        if (ActivityCopied != null)
        {
            ActivityModel = ActivityCopied.Clone();
        }

        await LoadCommesse();

        if (IsNew)
        {
            ActivityModel.EstimatedTime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour));
            ActivityModel.EstimatedEndtime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour) + TimeSpan.FromHours(1));
            ActivityModel.UserName = UserSession.User.Username;
        }

        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 != null)
        {
            foreach (var attached in AttachedList)
            {
                if (attached.Type != AttachedDTO.TypeAttached.Position) continue;

                var position = new PositionDTO
                {
                    Description = attached.Description,
                    Lat = attached.Lat,
                    Lng = attached.Lng
                };

                ActivityModel.Position = await IntegryApiService.SavePosition(position);
            }
        }
    }

    private async Task SaveAttached(string activityId)
    {
        if (AttachedList != null)
        {
            foreach (var attached in AttachedList)
            {
                if (attached.FileContent is not null && attached.Type != AttachedDTO.TypeAttached.Position)
                {
                    await IntegryApiService.UploadFile(activityId, attached.FileContent, attached.Name);
                }
            }
        }
    }

    private bool CheckPreSave()
    {
        Snackbar.Clear();

        if (!ActivityModel.ActivityTypeId.IsNullOrEmpty()) return true;
        Snackbar.Add("Tipo attività obbligatorio!", Severity.Error);

        return false;
    }

    private async Task LoadData()
    {
        if (!IsNew && Id != null)
        {
            ActivityFileList = await IntegryApiService.GetActivityFile(Id);
        }

        Users = await ManageData.GetTable<StbUser>();
        ActivityResult = await ManageData.GetTable<StbActivityResult>();
        Clienti = await ManageData.GetTable<AnagClie>(x => x.FlagStato.Equals("A"));
        Pros = await ManageData.GetTable<PtbPros>();
        ActivityType = await ManageData.GetTable<StbActivityType>(x => x.FlagTipologia.Equals("A"));
    }

    private async Task LoadCommesse() =>
        Commesse = await ManageData.GetTable<JtbComt>(x => x.CodAnag != null && x.CodAnag.Equals(ActivityModel.CodAnag));

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

        var listToReturn = new List<string>();

        listToReturn.AddRange(
            Clienti.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => $"{x.CodAnag} - {x.RagSoc}")
        );

        listToReturn.AddRange(
            Pros.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => $"{x.CodPpro} - {x.RagSoc}")
        );

        return listToReturn;
    }

    private async Task OnClienteChanged()
    {
        ActivityModel.CodJcom = null;

        if (ActivityModel.Cliente.IsNullOrEmpty()) return;

        var match = Regex.Match(ActivityModel.Cliente!, @"^\s*(\S+)\s*-\s*(.*)$");
        if (!match.Success)
            return;

        ActivityModel.CodAnag = match.Groups[1].Value;
        ActivityModel.Cliente = match.Groups[2].Value;

        await LoadCommesse();
        OnAfterChangeValue();
    }

    private async Task OnCommessaChanged()
    {
        ActivityModel.Commessa = (await ManageData.GetTable<JtbComt>(x => x.CodJcom.Equals(ActivityModel.CodJcom))).Last().Descrizione;
        OnAfterChangeValue();
    }

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

        if (ActivityModel.EstimatedEndtime <= ActivityModel.EstimatedTime)
        {
            ActivityModel.EstimatedEndtime = ActivityModel.EstimatedTime.Value.AddHours(1);
        }
    }

    private async Task OnAfterChangeEsito()
    {
        OnAfterChangeValue();

        // var result = await ConfirmMemo.ShowAsync();

        // if (result is true)
        //     OpenAddMemo = !OpenAddMemo;
    }

    private void OpenSelectEsito()
    {
        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;

                var resultNamePosition = await AddNamePosition.ShowAsync();

                if (resultNamePosition is true)
                    attached.Description = NamePosition;
                attached.Name = NamePosition!;
            }

            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(AttachedDTO attached)
    {
        if (attached is { FileContent: not null, MimeType: not null })
        {
            var fileViewerUrl = $"data:{attached.MimeType};base64,{Convert.ToBase64String(attached.FileContent)}";
            await ModalHelpers.OpenViewAttach(Dialog, fileViewerUrl);
        }
        else
        {
            Snackbar.Clear();
            Snackbar.Add("Impossibile aprire il file", Severity.Error);
        }
    }

    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(",", ".");

}