using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.API.Dto.Group;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.Profiles;
using LightlessSync.UI.Tags;
using LightlessSync.Utils;
using Microsoft.Extensions.Logging;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System.Numerics;

namespace LightlessSync.UI;

public partial class EditProfileUi
{
    private void OpenGroupEditor(GroupFullInfoDto groupInfo)
    {
        _mode = ProfileEditorMode.Group;
        _groupInfo = groupInfo;

        var profile = _lightlessProfileManager.GetLightlessGroupProfile(groupInfo.Group);
        _groupProfileData = profile;
        SyncGroupProfileState(profile, resetSelection: true);

        var scale = ImGuiHelpers.GlobalScale;
        var viewport = ImGui.GetMainViewport();
        ProfileEditorLayoutCoordinator.Enable(groupInfo.Group.GID);
        ProfileEditorLayoutCoordinator.EnsureAnchor(viewport.WorkPos, scale);
        Mediator.Publish(new GroupProfileOpenStandaloneMessage(groupInfo.Group));

        IsOpen = true;
        _wasOpen = true;
    }

    private void ResetGroupEditorState()
    {
        _groupInfo = null;
        _groupProfileData = null;
        _groupIsNsfw = false;
        _groupIsDisabled = false;
        _groupServerIsNsfw = false;
        _groupServerIsDisabled = false;
        _queuedProfileImage = null;
        _queuedBannerImage = null;
        _profileImage = Array.Empty<byte>();
        _bannerImage = Array.Empty<byte>();
        _profileDescription = string.Empty;
        _descriptionText = string.Empty;
        _profileTagIds = Array.Empty<int>();
        _tagEditorSelection.Clear();
        _pfpTextureWrap?.Dispose();
        _pfpTextureWrap = null;
        _bannerTextureWrap?.Dispose();
        _bannerTextureWrap = null;
        _showProfileImageError = false;
        _showBannerImageError = false;
        _groupVisibilityInitialized = false;
    }

    private void DrawGroupEditor(float scale)
    {
        if (_groupInfo is null)
        {
            UiSharedService.TextWrapped("Open the Syncshell admin panel and choose a group to edit its profile.");
            return;
        }

        var viewport = ImGui.GetMainViewport();
        var linked = ProfileEditorLayoutCoordinator.IsActive(_groupInfo.Group.GID);

        if (linked)
        {
            ProfileEditorLayoutCoordinator.EnsureAnchor(viewport.WorkPos, scale);

            var desiredSize = ProfileEditorLayoutCoordinator.GetEditorSize(scale);
            if (!ProfileEditorLayoutCoordinator.NearlyEquals(ImGui.GetWindowSize(), desiredSize))
                ImGui.SetWindowSize(desiredSize, ImGuiCond.Always);

            var currentPos = ImGui.GetWindowPos();
            if (IsWindowBeingDragged())
                ProfileEditorLayoutCoordinator.UpdateAnchorFromEditor(currentPos, scale);

            var desiredPos = ProfileEditorLayoutCoordinator.GetEditorPosition(scale);
            if (!ProfileEditorLayoutCoordinator.NearlyEquals(currentPos, desiredPos))
                ImGui.SetWindowPos(desiredPos, ImGuiCond.Always);
        }
        else
        {
            var defaultProfilePos = viewport.WorkPos + new Vector2(50f, 70f) * scale;
            var defaultEditorPos = defaultProfilePos + ProfileEditorLayoutCoordinator.GetEditorOffset(scale);
            ImGui.SetWindowPos(defaultEditorPos, ImGuiCond.FirstUseEver);
        }

        if (_queuedProfileImage is not null)
            ApplyQueuedGroupProfileImage();
        if (_queuedBannerImage is not null)
            ApplyQueuedGroupBannerImage();

        var profile = _lightlessProfileManager.GetLightlessGroupProfile(_groupInfo.Group);
        _groupProfileData = profile;
        SyncGroupProfileState(profile, resetSelection: false);

        var accent = UIColors.Get("LightlessPurple");
        var accentBg = new Vector4(accent.X, accent.Y, accent.Z, 0.015f);
        var accentBorder = new Vector4(accent.X, accent.Y, accent.Z, 0.07f);

        using var panelBg = ImRaii.PushColor(ImGuiCol.ChildBg, accentBg);
        using var panelBorder = ImRaii.PushColor(ImGuiCol.ChildBg, accentBorder);
        ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);

        if (ImGui.BeginChild("##GroupProfileEditorCanvas", -Vector2.One, true))
        {
            DrawGroupGuidelinesSection(scale);
            ImGui.Dummy(new Vector2(0f, 4f * scale));
            DrawGroupProfileContent(profile, scale);
        }

        ImGui.EndChild();
        ImGui.PopStyleVar();
    }

    private void DrawGroupGuidelinesSection(float scale)
    {
        DrawSection("Guidelines", scale, () =>
        {
            ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1f, 1f));

            _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "All users that are paired and unpaused with you will be able to see your profile pictures, tags and description.");
            _uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "Other users have the possibility to report this profile for breaking the rules.");
            _uiSharedService.DrawNoteLine("!!! ", UIColors.Get("DimRed"), "AVOID: Anything as profile image that can be considered highly illegal or obscene (bestiality, anything that could be considered a sexual act with a minor (that includes Lalafells), etc.)");
            _uiSharedService.DrawNoteLine("!!! ", UIColors.Get("DimRed"), "AVOID: Slurs of any kind in the description that can be considered highly offensive");
            _uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "In case of valid reports from other users this can lead to disabling the profile forever or terminating syncshell owner's Lightless account indefinitely.");
            _uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "Judgement of the profile validity from reports through staff is not up to debate and the decisions to disable the profile or your account permanent.");
            _uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessBlue"), "If the profile picture or profile description could be considered NSFW, enable the toggle in visibility settings.");

            ImGui.PopStyleVar();
        });
    }

    private void DrawGroupProfileContent(LightlessGroupProfileData profile, float scale)
    {
        DrawSection("Profile Preview", scale, () => DrawGroupProfileSnapshot(profile, scale));
        DrawSection("Profile Image", scale, DrawGroupProfileImageControls);
        DrawSection("Profile Banner", scale, DrawGroupProfileBannerControls);
        DrawSection("Profile Description", scale, DrawGroupProfileDescriptionEditor);
        DrawSection("Profile Tags", scale, () => DrawGroupProfileTagsEditor(scale));
        DrawSection("Visibility", scale, DrawGroupProfileVisibilityControls);
    }

    private void DrawGroupProfileSnapshot(LightlessGroupProfileData profile, float scale)
    {
        var bannerHeight = 140f * scale;
        ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
        if (ImGui.BeginChild("##GroupProfileBannerPreview", new Vector2(-1f, bannerHeight), true))
        {
            if (_bannerTextureWrap != null)
            {
                var childSize = ImGui.GetWindowSize();
                var padding = ImGui.GetStyle().WindowPadding;
                var contentSize = new Vector2(
                    MathF.Max(childSize.X - padding.X * 2f, 1f),
                    MathF.Max(childSize.Y - padding.Y * 2f, 1f));

                var imageSize = ImGuiHelpers.ScaledVector2(_bannerTextureWrap.Width, _bannerTextureWrap.Height);
                if (imageSize.X > contentSize.X || imageSize.Y > contentSize.Y)
                {
                    var ratio = MathF.Min(contentSize.X / MathF.Max(imageSize.X, 1f), contentSize.Y / MathF.Max(imageSize.Y, 1f));
                    imageSize *= ratio;
                }

                var offset = new Vector2(
                    MathF.Max((contentSize.X - imageSize.X) * 0.5f, 0f),
                    MathF.Max((contentSize.Y - imageSize.Y) * 0.5f, 0f));
                ImGui.SetCursorPos(padding + offset);
                ImGui.Image(_bannerTextureWrap.Handle, imageSize);
            }
            else
            {
                ImGui.TextColored(UIColors.Get("LightlessPurple"), "No profile banner uploaded.");
            }
        }
        ImGui.EndChild();
        ImGui.PopStyleVar();

        ImGui.Dummy(new Vector2(0f, 6f * scale));

        if (_pfpTextureWrap != null)
        {
            var size = ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height);
            var maxEdge = 160f * scale;
            if (size.X > maxEdge || size.Y > maxEdge)
            {
                var ratio = MathF.Min(maxEdge / MathF.Max(size.X, 1f), maxEdge / MathF.Max(size.Y, 1f));
                size *= ratio;
            }

            ImGui.Image(_pfpTextureWrap.Handle, size);
        }
        else
        {
            ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
            if (ImGui.BeginChild("##GroupProfileImagePlaceholder", new Vector2(160f * scale, 160f * scale), true))
                ImGui.TextColored(UIColors.Get("LightlessPurple"), "No profile picture uploaded.");
            ImGui.EndChild();
            ImGui.PopStyleVar();
        }

        ImGui.SameLine();
        ImGui.BeginGroup();
        ImGui.TextColored(UIColors.Get("LightlessBlue"), _groupInfo!.GroupAliasOrGID);
        ImGui.TextDisabled($"ID: {_groupInfo.Group.GID}");
        ImGui.TextDisabled($"Owner: {_groupInfo.Owner.AliasOrUID}");
        ImGui.EndGroup();

        ImGui.Dummy(new Vector2(0f, 4f * scale));
        ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
        if (ImGui.BeginChild("##GroupProfileDescriptionPreview", new Vector2(-1f, 120f * scale), true))
        {
            var hasDescription = !string.IsNullOrWhiteSpace(profile.Description);
            ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X);
            if (!hasDescription)
            {
                ImGui.TextDisabled("Syncshell has no description set.");
            }
            else if (!SeStringUtils.TryRenderSeStringMarkupAtCursor(profile.Description!))
            {
                UiSharedService.TextWrapped(profile.Description);
            }
            ImGui.PopTextWrapPos();
        }
        ImGui.EndChild();
        ImGui.PopStyleVar();

    }

    private void DrawGroupProfileImageControls()
    {
        _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "Profile pictures must be 512x512 and under 2 MiB.");

        if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
        {
            _fileDialogManager.OpenFileDialog("Select syncshell profile picture", _imageFileDialogFilter, (success, file) =>
            {
                if (!success || string.IsNullOrEmpty(file))
                    return;
                _showProfileImageError = false;
                _ = SubmitGroupProfilePicture(file);
            });
        }
        UiSharedService.AttachToolTip("Select an image up to 512x512 pixels and <= 2 MiB (PNG/JPG/JPEG/WEBP/BMP).");
        ImGui.SameLine();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear profile picture"))
        {
            _ = ClearGroupProfilePicture();
        }
        UiSharedService.AttachToolTip("Remove the current profile picture from this syncshell.");

        if (_showProfileImageError)
        {
            UiSharedService.ColorTextWrapped("Image must be no larger than 512x512 pixels and under 2 MiB.", ImGuiColors.DalamudRed);
        }
    }

    private void DrawGroupProfileBannerControls()
    {
        _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "Profile banners must be 840x260 and under 2 MiB.");

        if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile banner"))
        {
            _fileDialogManager.OpenFileDialog("Select syncshell profile banner", _imageFileDialogFilter, (success, file) =>
            {
                if (!success || string.IsNullOrEmpty(file))
                    return;
                _showBannerImageError = false;
                _ = SubmitGroupProfileBanner(file);
            });
        }
        UiSharedService.AttachToolTip("Select an image up to 840x260 pixels and <= 2 MiB (PNG/JPG/JPEG/WEBP/BMP).");
        ImGui.SameLine();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear profile banner"))
        {
            _ = ClearGroupProfileBanner();
        }
        UiSharedService.AttachToolTip("Remove the current profile banner.");

        if (_showBannerImageError)
        {
            UiSharedService.ColorTextWrapped("Banner must be no larger than 840x260 pixels and under 2 MiB.", ImGuiColors.DalamudRed);
        }
    }

    private void DrawGroupProfileDescriptionEditor()
    {
        ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(6f, 4f) * ImGuiHelpers.GlobalScale);
        var descriptionBoxSize = new Vector2(-1f, 160f * ImGuiHelpers.GlobalScale);
        ImGui.InputTextMultiline("##GroupDescription", ref _descriptionText, 1500, descriptionBoxSize);
        ImGui.PopStyleVar();

        ImGui.TextDisabled($"{_descriptionText.Length}/1500 characters");
        ImGui.SameLine();
        ImGuiComponents.HelpMarker(DescriptionMacroTooltip);

        bool changed = !string.Equals(_descriptionText, _profileDescription, StringComparison.Ordinal);
        if (!changed)
            ImGui.BeginDisabled();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Description"))
        {
            _ = SubmitGroupDescription(_descriptionText);
        }
        UiSharedService.AttachToolTip("Apply the text above to the syncshell profile description.");
        if (!changed)
            ImGui.EndDisabled();

        ImGui.SameLine();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear Description"))
        {
            _ = SubmitGroupDescription(string.Empty);
        }
        UiSharedService.AttachToolTip("Remove the profile description.");
    }

    private void DrawGroupProfileTagsEditor(float scale)
    {
        DrawTagEditor(
            scale,
            contextPrefix: "group",
            saveTooltip: "Apply the selected tags to this syncshell profile.",
            submitAction: payload => SubmitGroupTagChanges(payload),
            allowReorder: true,
            sortPayloadBeforeSubmit: false,
            onPayloadPrepared: payload =>
            {
                _tagEditorSelection.Clear();
                if (payload.Length > 0)
                    _tagEditorSelection.AddRange(payload);
            });
    }

    private void DrawGroupProfileVisibilityControls()
    {
        EnsureGroupVisibilityStateInitialised();

        bool changedNsfw = DrawCheckboxRow("Profile is NSFW", _groupIsNsfw, out var newNsfw, "Flag this profile as not safe for work.");
        if (changedNsfw)
            _groupIsNsfw = newNsfw;

        bool changedDisabled = DrawCheckboxRow("Disable profile for viewers", _groupIsDisabled, out var newDisabled, "Temporarily hide this profile from members.");
        if (changedDisabled)
            _groupIsDisabled = newDisabled;

        bool visibilityChanged = (_groupIsNsfw != _groupServerIsNsfw) || (_groupIsDisabled != _groupServerIsDisabled);

        if (!visibilityChanged)
            ImGui.BeginDisabled();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Apply Visibility Changes"))
        {
            _ = SubmitGroupVisibilityChanges(_groupIsNsfw, _groupIsDisabled);
        }
        UiSharedService.AttachToolTip("Apply the visibility toggles above.");
        if (!visibilityChanged)
            ImGui.EndDisabled();

        ImGui.SameLine();
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.SyncAlt, "Reset"))
        {
            _groupIsNsfw = _groupServerIsNsfw;
            _groupIsDisabled = _groupServerIsDisabled;
        }
    }

    private string? GetCurrentGroupProfileImageBase64()
    {
        if (_queuedProfileImage is not null && _queuedProfileImage.Length > 0)
            return Convert.ToBase64String(_queuedProfileImage);

        if (!string.IsNullOrWhiteSpace(_groupProfileData?.Base64ProfilePicture))
            return _groupProfileData!.Base64ProfilePicture;

        return _profileImage.Length > 0 ? Convert.ToBase64String(_profileImage) : null;
    }

    private string? GetCurrentGroupBannerBase64()
    {
        if (_queuedBannerImage is not null && _queuedBannerImage.Length > 0)
            return Convert.ToBase64String(_queuedBannerImage);

        if (!string.IsNullOrWhiteSpace(_groupProfileData?.Base64BannerPicture))
            return _groupProfileData!.Base64BannerPicture;

        return _bannerImage.Length > 0 ? Convert.ToBase64String(_bannerImage) : null;
    }

    private async Task SubmitGroupProfilePicture(string filePath)
    {
        if (_groupInfo is null)
            return;

        try
        {
            var fileContent = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
            var stream = new MemoryStream(fileContent);
            await using (stream.ConfigureAwait(false))
            {
                var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
            if (!IsSupportedImageFormat(format))
            {
                _showProfileImageError = true;
                return;
            }

            using var image = Image.Load<Rgba32>(fileContent);
            if (image.Width > 512 || image.Height > 512 || fileContent.Length > 2000 * 1024)
            {
                _showProfileImageError = true;
                return;
            }

            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: null,
                Tags: null,
                PictureBase64: Convert.ToBase64String(fileContent),
                BannerBase64: null,
                IsNsfw: null,
                IsDisabled: null)).ConfigureAwait(false);

            _showProfileImageError = false;
            _queuedProfileImage = fileContent;
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to upload syncshell profile picture.");
        }
    }

    private async Task ClearGroupProfilePicture()
    {
        if (_groupInfo is null)
            return;

        try
        {
            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: null,
                Tags: null,
                PictureBase64: null,
                BannerBase64: null,
                IsNsfw: null,
                IsDisabled: null)).ConfigureAwait(false);

            _queuedProfileImage = Array.Empty<byte>();
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to clear syncshell profile picture.");
        }
    }

    private async Task SubmitGroupProfileBanner(string filePath)
    {
        if (_groupInfo is null)
            return;

        try
        {
            var fileContent = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
            var stream = new MemoryStream(fileContent);
            await using (stream.ConfigureAwait(false))
            {
                var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
                if (!IsSupportedImageFormat(format))
                {
                    _showBannerImageError = true;
                    return;
                }

                using var image = Image.Load<Rgba32>(fileContent);
                if (image.Width > 840 || image.Height > 260 || fileContent.Length > 2000 * 1024)
                {
                    _showBannerImageError = true;
                    return;
                }

                await _apiController.GroupSetProfile(new GroupProfileDto(
                    _groupInfo.Group,
                    Description: null,
                    Tags: null,
                    PictureBase64: null,
                    BannerBase64: Convert.ToBase64String(fileContent),
                    IsNsfw: null,
                    IsDisabled: null)).ConfigureAwait(false);

                _showBannerImageError = false;
                _queuedBannerImage = fileContent;
                Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to upload syncshell profile banner.");
        }
    }

    private async Task ClearGroupProfileBanner()
    {
        if (_groupInfo is null)
            return;

        try
        {
            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: null,
                Tags: null,
                PictureBase64: null,
                BannerBase64: null,
                IsNsfw: null,
                IsDisabled: null)).ConfigureAwait(false);

            _queuedBannerImage = Array.Empty<byte>();
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to clear syncshell profile banner.");
        }
    }

    private async Task SubmitGroupDescription(string description)
    {
        if (_groupInfo is null)
            return;

        try
        {
            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: description,
                Tags: null,
                PictureBase64: GetCurrentGroupProfileImageBase64(),
                BannerBase64: GetCurrentGroupBannerBase64(),
                IsNsfw: null,
                IsDisabled: null)).ConfigureAwait(false);

            _profileDescription = description;
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to update syncshell profile description.");
        }
    }

    private void EnsureGroupVisibilityStateInitialised()
    {
        if (_groupInfo == null || _groupVisibilityInitialized)
            return;

        _groupIsNsfw = _groupServerIsNsfw;
        _groupIsDisabled = _groupServerIsDisabled;
        _groupVisibilityInitialized = true;
    }

    private async Task SubmitGroupTagChanges(int[] payload)
    {
        if (_groupInfo is null)
            return;

        try
        {
            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: null,
                Tags: payload,
                PictureBase64: GetCurrentGroupProfileImageBase64(),
                BannerBase64: GetCurrentGroupBannerBase64(),
                IsNsfw: null,
                IsDisabled: null)).ConfigureAwait(false);

            _profileTagIds = payload.Length == 0 ? [] : [.. payload];
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to update syncshell profile tags.");
        }
    }

    private async Task SubmitGroupVisibilityChanges(bool isNsfw, bool isDisabled)
    {
        if (_groupInfo is null)
            return;

        try
        {
            await _apiController.GroupSetProfile(new GroupProfileDto(
                _groupInfo.Group,
                Description: null,
                Tags: null,
                PictureBase64: GetCurrentGroupProfileImageBase64(),
                BannerBase64: GetCurrentGroupBannerBase64(),
                IsNsfw: isNsfw,
                IsDisabled: isDisabled)).ConfigureAwait(false);

            _groupServerIsNsfw = isNsfw;
            _groupServerIsDisabled = isDisabled;
            Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to update syncshell profile visibility.");
        }
    }

    private void ApplyQueuedGroupProfileImage()
    {
        if (_queuedProfileImage is null)
            return;

        _profileImage = _queuedProfileImage;
        _pfpTextureWrap?.Dispose();
        _pfpTextureWrap = _profileImage.Length > 0 ? _uiSharedService.LoadImage(_profileImage) : null;
        _queuedProfileImage = null;
    }

    private void ApplyQueuedGroupBannerImage()
    {
        if (_queuedBannerImage is null)
            return;

        _bannerImage = _queuedBannerImage;
        _bannerTextureWrap?.Dispose();
        _bannerTextureWrap = _bannerImage.Length > 0 ? _uiSharedService.LoadImage(_bannerImage) : null;
        _queuedBannerImage = null;
    }

    private void SyncGroupProfileState(LightlessGroupProfileData profile, bool resetSelection)
    {
        if (!_profileImage.SequenceEqual(profile.ProfileImageData.Value))
        {
            _profileImage = profile.ProfileImageData.Value;
            _pfpTextureWrap?.Dispose();
            _pfpTextureWrap = _profileImage.Length > 0 ? _uiSharedService.LoadImage(_profileImage) : null;
        }

        if (!_bannerImage.SequenceEqual(profile.BannerImageData.Value))
        {
            _bannerImage = profile.BannerImageData.Value;
            _bannerTextureWrap?.Dispose();
            _bannerTextureWrap = _bannerImage.Length > 0 ? _uiSharedService.LoadImage(_bannerImage) : null;
        }

        if (!string.Equals(_profileDescription, profile.Description, StringComparison.Ordinal))
        {
            _profileDescription = profile.Description;
            _descriptionText = _profileDescription;
        }

        var tags = profile.Tags ?? Array.Empty<int>();
        if (!TagsEqual(tags, _profileTagIds))
        {
            _profileTagIds = tags.Count == 0 ? Array.Empty<int>() : tags.ToArray();
            if (resetSelection)
            {
                _tagEditorSelection.Clear();
                if (_profileTagIds.Length > 0)
                    _tagEditorSelection.AddRange(_profileTagIds);
            }
        }

        _groupServerIsNsfw = profile.IsNsfw;
        _groupServerIsDisabled = profile.IsDisabled;

        if (!_groupVisibilityInitialized)
        {
            _groupIsNsfw = _groupServerIsNsfw;
            _groupIsDisabled = _groupServerIsDisabled;
            _groupVisibilityInitialized = true;
        }
    }
}

