using SharpChat.ClientCommands;
using System.Globalization;
using System.Text;

namespace SharpChat;

public class User(
    string userId,
    string userName,
    ColourInheritable colour,
    int rank,
    UserPermissions perms,
    string nickName = "",
    UserStatus status = UserStatus.Online,
    string statusText = ""
) {
    public const int DEFAULT_SIZE = 30;
    public const int DEFAULT_MINIMUM_DELAY = 10000;
    public const int DEFAULT_RISKY_OFFSET = 5;

    public string UserId { get; } = userId;
    public string UserName { get; set; } = userName ?? throw new ArgumentNullException(nameof(userName));
    public ColourInheritable Colour { get; set; } = colour;
    public int Rank { get; set; } = rank;
    public UserPermissions Permissions { get; set; } = perms;
    public string NickName { get; set; } = nickName;
    public UserStatus Status { get; set; } = status;
    public string StatusText { get; set; } = statusText;

    public string LegacyName => string.IsNullOrWhiteSpace(NickName) ? UserName : $"~{NickName}";

    public string LegacyNameWithStatus {
        get {
            StringBuilder sb = new();

            if(Status == UserStatus.Away) {
                string statusText = StatusText.Trim();
                StringInfo sti = new(statusText);
                if(Encoding.UTF8.GetByteCount(statusText) > AFKClientCommand.MAX_BYTES
                    || sti.LengthInTextElements > AFKClientCommand.MAX_GRAPHEMES)
                    statusText = sti.SubstringByTextElements(0, Math.Min(sti.LengthInTextElements, AFKClientCommand.MAX_GRAPHEMES)).Trim();

                sb.AppendFormat("<{0}>_", statusText.ToUpperInvariant());
            }

            sb.Append(LegacyName);

            return sb.ToString();
        }
    }

    public bool Can(UserPermissions perm, bool strict = false) {
        UserPermissions perms = Permissions & perm;
        return strict ? perms == perm : perms > 0;
    }

    public bool NameEquals(string name) {
        return string.Equals(name, UserName, StringComparison.InvariantCultureIgnoreCase)
            || string.Equals(name, NickName, StringComparison.InvariantCultureIgnoreCase)
            || string.Equals(name, LegacyName, StringComparison.InvariantCultureIgnoreCase)
            || string.Equals(name, LegacyNameWithStatus, StringComparison.InvariantCultureIgnoreCase);
    }

    public override int GetHashCode() {
        return UserId.GetHashCode();
    }

    public static string GetDMChannelName(User user1, User user2) {
        return string.Compare(user1.UserId, user2.UserId, StringComparison.InvariantCultureIgnoreCase) > 0
            ? $"@{user2.UserId}-{user1.UserId}"
            : $"@{user1.UserId}-{user2.UserId}";
    }
}