using System.Text.Json;
using System.Text.RegularExpressions;
using YMhut.Box.Core.Api;

namespace YMhut.Box.Core.Tools;

public sealed record QqProfileResult(
    string Qq,
    string AvatarUrl,
    IReadOnlyDictionary<string, string> Fields,
    string SourceName,
    bool ProfileAvailable,
    string StatusMessage);

public static class QqProfileProvider
{
    private const string SourceName = "Uapis QQ User Info";

    public static async Task<QqProfileResult> QueryAsync(
        string input,
        IApiManager? apiManager,
        CancellationToken cancellationToken,
        string language = "zh-CN")
    {
        var qq = Regex.Match(input, @"\d{5,12}").Value;
        if (string.IsNullOrWhiteSpace(qq))
        {
            qq = "10000";
        }

        var avatarUrl = AvatarUrl(qq);
        var fields = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
        {
            ["QQ"] = qq
        };

        if (apiManager is null)
        {
            return new QqProfileResult(
                qq,
                avatarUrl,
                fields,
                "qlogo.cn",
                false,
                T(language, "资料源未配置，已展示默认 QQ 头像。", "Profile source is not configured; default QQ avatar is shown."));
        }

        try
        {
            var response = await apiManager.FetchAsync("qq_avatar", qq, cancellationToken).ConfigureAwait(false);
            if (!response.Success || string.IsNullOrWhiteSpace(response.Content))
            {
                return new QqProfileResult(
                    qq,
                    avatarUrl,
                    fields,
                    SourceName,
                    false,
                    response.Error ?? T(language, "资料源未返回可用内容。", "Profile source returned no usable content."));
            }

            var parsed = ParseProfile(response.Content, qq);
            foreach (var pair in parsed.Fields)
            {
                fields[pair.Key] = pair.Value;
            }

            if (IsAbsoluteHttpUrl(parsed.AvatarUrl))
            {
                avatarUrl = parsed.AvatarUrl;
            }

            if (!fields.ContainsKey("头像") && IsAbsoluteHttpUrl(avatarUrl))
            {
                fields["头像"] = avatarUrl;
            }

            var available = fields.Count > 1;
            return new QqProfileResult(
                qq,
                avatarUrl,
                fields,
                SourceName,
                available,
                available
                    ? T(language, "资料字段来自新版 QQ 信息源；请求地址已隐藏，响应中的头像链接可展示。", "Profile fields came from the new QQ information source; request URL is hidden and returned avatar links can be displayed.")
                    : T(language, "资料源未返回昵称、签名、等级或会员信息。", "Profile source did not return nickname, signature, level, or membership fields."));
        }
        catch (Exception exception)
        {
            return new QqProfileResult(qq, avatarUrl, fields, SourceName, false, SensitiveText.Sanitize(exception.Message));
        }
    }

    public static string AvatarUrl(string qq) => $"https://q1.qlogo.cn/g?b=qq&nk={Uri.EscapeDataString(qq)}&s=640";

    private static ParsedProfile ParseProfile(string content, string qq)
    {
        var fields = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        var avatarUrl = string.Empty;
        var text = content.Trim();
        if (text.Contains("portraitCallBack", StringComparison.OrdinalIgnoreCase))
        {
            var nicknameMatch = Regex.Match(text, @$"""{Regex.Escape(qq)}""\s*:\s*\[[^\]]*?""(?<nickname>[^""]+)""");
            if (nicknameMatch.Success)
            {
                fields["昵称"] = nicknameMatch.Groups["nickname"].Value;
            }

            return new ParsedProfile(fields, avatarUrl);
        }

        try
        {
            using var document = JsonDocument.Parse(text);
            var root = document.RootElement;
            if (root.ValueKind == JsonValueKind.Object &&
                root.TryGetProperty("data", out var data) &&
                data.ValueKind == JsonValueKind.Object)
            {
                root = data;
            }

            AddIfPresent(fields, root, "QQ", "qq", "uin");
            AddIfPresent(fields, root, "用户 ID", "user_id", "userId");
            AddIfPresent(fields, root, "昵称", "nickname", "nick", "name");
            AddIfPresent(fields, root, "个性签名", "long_nick", "longNick", "signature", "sign");
            AddIfPresent(fields, root, "头像", "avatar_url", "avatarUrl", "avatar", "headimgurl", "figureurl");
            AddIfPresent(fields, root, "年龄", "age");
            AddIfPresent(fields, root, "性别", "sex", "gender");
            AddIfPresent(fields, root, "QID", "qid");
            AddIfPresent(fields, root, "QQ 等级", "qq_level", "qqLevel", "level");
            AddIfPresent(fields, root, "QQ 等级图标", "qq_level_icons", "qqLevelIcons");
            AddIfPresent(fields, root, "位置", "location", "region", "area", "province", "city");
            AddIfPresent(fields, root, "邮箱", "email");
            AddIfPresent(fields, root, "VIP", "is_vip", "vip");
            AddIfPresent(fields, root, "年费 VIP", "is_years_vip", "years_vip", "isYearsVip");
            AddIfPresent(fields, root, "SVIP", "is_svip", "svip", "isSvip");
            AddIfPresent(fields, root, "QQ 大会员", "is_big_club", "big_club", "isBigClub");
            AddIfPresent(fields, root, "会员状态", "vip_status", "vipStatus");
            AddIfPresent(fields, root, "会员类型", "vip_type", "vipType");
            AddIfPresent(fields, root, "VIP 等级", "vip_level", "vipLevel");
            AddIfPresent(fields, root, "QQ 大会员等级", "big_club_level", "bigClubLevel");
            AddIfPresent(fields, root, "黄钻等级", "yellow_diamond_level", "yellowDiamondLevel");
            AddIfPresent(fields, root, "绿钻等级", "green_diamond_level", "greenDiamondLevel");
            AddIfPresent(fields, root, "腾讯视频会员等级", "video_vip_level", "videoVipLevel");
            AddIfPresent(fields, root, "情侣会员等级", "lover_vip_level", "loverVipLevel");
            AddIfPresent(fields, root, "注册时间", "reg_time", "regTime", "registerTime", "registrationTime", "createdAt");
            AddIfPresent(fields, root, "最后更新时间", "last_updated", "lastUpdated", "updatedAt");

            if (TryFind(root, "privilege_icons", out var icons) && !string.IsNullOrWhiteSpace(icons))
            {
                fields["特权图标"] = icons;
            }

            if (fields.TryGetValue("头像", out var parsedAvatar) && IsAbsoluteHttpUrl(parsedAvatar))
            {
                avatarUrl = parsedAvatar;
            }
        }
        catch
        {
        }

        return new ParsedProfile(fields, avatarUrl);
    }

    private static void AddIfPresent(Dictionary<string, string> fields, JsonElement root, string label, params string[] names)
    {
        foreach (var name in names)
        {
            if (TryFind(root, name, out var value) && !string.IsNullOrWhiteSpace(value))
            {
                fields[label] = value;
                return;
            }
        }
    }

    private static bool TryFind(JsonElement element, string name, out string value)
    {
        value = string.Empty;
        if (element.ValueKind == JsonValueKind.Object)
        {
            foreach (var property in element.EnumerateObject())
            {
                if (property.NameEquals(name))
                {
                    value = StringValue(property.Value);
                    return true;
                }

                if (TryFind(property.Value, name, out value))
                {
                    return true;
                }
            }
        }
        else if (element.ValueKind == JsonValueKind.Array)
        {
            foreach (var item in element.EnumerateArray())
            {
                if (TryFind(item, name, out value))
                {
                    return true;
                }
            }
        }

        return false;
    }

    private static string StringValue(JsonElement value)
    {
        return value.ValueKind switch
        {
            JsonValueKind.String => value.GetString() ?? string.Empty,
            JsonValueKind.Number => value.GetRawText(),
            JsonValueKind.True => "是",
            JsonValueKind.False => "否",
            JsonValueKind.Null => string.Empty,
            JsonValueKind.Object or JsonValueKind.Array => JsonSerializer.Serialize(value),
            _ => value.GetRawText()
        };
    }

    private static bool IsAbsoluteHttpUrl(string value)
    {
        return Uri.TryCreate(value, UriKind.Absolute, out var uri) &&
            uri.Scheme is "http" or "https";
    }

    private static bool English(string? language) => string.Equals(language, "en-US", StringComparison.OrdinalIgnoreCase);

    private static string T(string? language, string zh, string en) => English(language) ? en : zh;

    private sealed record ParsedProfile(IReadOnlyDictionary<string, string> Fields, string AvatarUrl);
}
