using Microsoft.UI.Xaml.Controls;
using Sonex.Data.Records;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Logger = Sonex.Client.Helpers.Logger;

namespace Sonex.Client.Dialogs;

public sealed partial class SendSessionsMessageDialog : ContentDialog
{
    private readonly List<ActiveSessionRecord> _selectedSessions = new();
    private readonly List<SessionTarget> _targetSessions = new();
    private int _duplicateSessionCount;
    private int _missingInstanceCount;

    public SendSessionsMessageDialog()
    {
        InitializeComponent();
        UpdateDescription();
    }

    public int SelectedSessionCount => _selectedSessions.Count;
    public int TargetInstanceCount => _targetSessions.Count;
    public int DuplicateSessionCount => _duplicateSessionCount;
    public int MissingInstanceCount => _missingInstanceCount;

    public static SendSessionsMessageDialog CreateForSessions(IEnumerable<ActiveSessionRecord> sessions)
    {
        var dialog = new SendSessionsMessageDialog();
        dialog.ConfigureSessions(sessions);
        return dialog;
    }

    public void ConfigureSessions(IEnumerable<ActiveSessionRecord> sessions)
    {
        _selectedSessions.Clear();
        _targetSessions.Clear();
        _duplicateSessionCount = 0;
        _missingInstanceCount = 0;

        if (sessions != null)
            _selectedSessions.AddRange(sessions.Where(x => x != null));

        var seenInstanceIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        foreach (var session in _selectedSessions)
        {
            var instanceId = Normalize(session.InstanceId);
            if (string.IsNullOrWhiteSpace(instanceId))
            {
                _missingInstanceCount++;
                continue;
            }

            if (!seenInstanceIds.Add(instanceId))
            {
                _duplicateSessionCount++;
                continue;
            }

            _targetSessions.Add(new SessionTarget(instanceId));
        }

        UpdateDescription();
    }

    private void UpdateDescription()
    {
        _Message.Text = string.Empty;
        IsPrimaryButtonEnabled = _targetSessions.Count > 0;

        if (_selectedSessions.Count == 0)
        {
            _Description.Text = "Select at least one session before sending a message.";
            return;
        }

        if (_targetSessions.Count == 0)
        {
            _Description.Text = "None of the selected sessions contain a valid instance identifier, so no message can be sent.";
            return;
        }

        var parts = new List<string>
        {
            $"The message will be sent to {FormatCount(_targetSessions.Count, "instance", "instances")}."
        };

        if (_duplicateSessionCount > 0 || _missingInstanceCount > 0)
            parts.Add("Some selected sessions will be skipped.");

        _Description.Text = string.Join(" ", parts);
    }

    private async void SendSessionsMessageDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
    {
        var deferral = args.GetDeferral();
        args.Cancel = true;

        try
        {
            _Message.Text = string.Empty;
            IsPrimaryButtonEnabled = false;
            IsSecondaryButtonEnabled = false;

            if (_targetSessions.Count == 0)
            {
                _Message.Text = "There is no valid target instance for this message.";
                return;
            }

            var title = Normalize(TitleBox.Text);
            var message = Normalize(MessageBox.Text);

            if (string.IsNullOrWhiteSpace(message))
            {
                _Message.Text = "Message cannot be empty.";
                return;
            }

            await SendAsync(title, message);
            args.Cancel = false;
        }
        catch (Exception ex)
        {
            string errorId = Logger.Error(
                ex,
                source: nameof(SendSessionsMessageDialog),
                operation: "SendSessionsMessageDialog_PrimaryButtonClick");
            _Message.Text = Logger.BuildUserMessage(errorId);
        }
        finally
        {
            IsPrimaryButtonEnabled = _targetSessions.Count > 0;
            IsSecondaryButtonEnabled = true;
            deferral.Complete();
        }
    }

    private async Task SendAsync(string? title, string message)
    {
        foreach (var target in _targetSessions)
            await ActiveSessionRecord.SendMessage(title ?? string.Empty, message, target.InstanceId);
    }

    private static string FormatCount(int count, string singular, string plural)
    {
        return count == 1
            ? $"1 {singular}"
            : $"{count} {plural}";
    }

    private static string? Normalize(string? value)
    {
        return string.IsNullOrWhiteSpace(value)
            ? null
            : value.Trim();
    }

    private sealed class SessionTarget
    {
        public SessionTarget(string instanceId)
        {
            InstanceId = instanceId;
        }

        public string InstanceId { get; }
    }
}
