using System.Windows.Controls;
using System.Windows.Input;
using PCL.Core.App;
using PCL.Core.App.Localization;
using PCL.Core.UI.Controls;
using PCL.Core.Utils;
using PCL.Core.IO.Net.Http;
using System.Text.Json.Serialization;

namespace PCL;

public partial class MyMsgLogin
{
    private readonly JsonObject data;
    private string deviceCode; // 用于轮询的设备代码
    private string oAuthUrl = ""; // OAuth 轮询验证地址
    private string userCode; // 需要用户在网页上输入的设备代码
    private string website; // 验证网页的网址
    private Task? workingThread;

    public MyMsgLogin()
    {
        InitializeComponent();
        // Handles
        Loaded += Load;
        Btn1.Click += Btn1_Click;
        Btn3.Click += Btn3_Click;
        PanBorder.MouseLeftButtonDown += Drag;
        LabTitle.MouseLeftButtonDown += Drag;
    }

    private void Finished(object result)
    {
        if (myConverter.IsExited)
            return;
        myConverter.IsExited = true;
        myConverter.Result = result;
        ModBase.RunInUi(Close);
        Thread.Sleep(200);
        ModMain.frmMain.ShowWindowToTop();
    }

    private void Init()
    {
        userCode = (string)data["user_code"];
        deviceCode = (string)data["device_code"];
        ModBase.ClipboardSet(deviceCode);
        if (data["verification_uri_complete"] is not null)
        {
            website = (string)data["verification_uri_complete"];
            LabCaption.Text = Lang.Text("Launch.Account.LoginDialog.MicrosoftInstructions.WithAutoFill", userCode, website);
        }
        else
        {
            website = (string)data["verification_uri"];
            LabCaption.Text = Lang.Text("Launch.Account.LoginDialog.MicrosoftInstructions", userCode, website);
        }

        // 设置 UI
        LabTitle.Text = Lang.Text("Launch.Account.LoginDialog.MinecraftLogin");
        CustomEventService.SetEventData(Btn1, website);
        CustomEventService.SetEventData(Btn2, userCode);
        // 启动工作线程
        workingThread = WorkThreadAsync();
    }

    private record ErrorBody(
        [property: JsonPropertyName("error")] string Error,
        [property: JsonPropertyName("error_description")] string Desc);

    private async Task WorkThreadAsync()
    {
        await Task.Delay(2000).ConfigureAwait(false);
        if (myConverter.IsExited)
            return;
        ModBase.OpenWebsite(website);
        ModBase.ClipboardSet(userCode);
        var delayTime = (data["interval"].ToObject<int>() - 1) * 1000;
        // 轮询
        var unknownFailureCount = 0;
        while (!myConverter.IsExited)
        {
            try
            {
                var bodyData = $"grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id={Secrets.MSOAuthClientId}&device_code={deviceCode}&scope=XboxLive.signin%20offline_access";
                using var result = await HttpRequest
                    .Create("https://login.microsoftonline.com/consumers/oauth2/v2.0/token")
                    .WithFormContent(bodyData)
                    .SendAsync(enableLogging: false)
                    .ConfigureAwait(false);
                if (!result.IsSuccess)
                {
                    var error = await result.AsJsonAsync<ErrorBody>()
                        .ConfigureAwait(false);
                    switch(error?.Error)
                    {
                        case "authorization_pending":
                            {
                                await Task.Delay(delayTime)
                                    .ConfigureAwait(false);
                                continue;
                            }
                        default:
                            {
                                throw new Exception(error?.Error ?? "Unable to get body");
                            }
                    }
                }
                // 获取结果
                var ctx = await result.AsStringAsync().ConfigureAwait(false);
                var resultJson = (JsonObject)ModBase.GetJson(ctx);
                ModProfile.ProfileLog($"令牌过期时间：{resultJson["expires_in"]} 秒");
                HintService.Hint(Lang.Text("Launch.Account.LoginDialog.Success"), HintType.Success);
                Finished(new[] { resultJson["access_token"].ToString(), resultJson["refresh_token"].ToString() });
                return;
            }
            catch (Exception ex)
            {
                if (unknownFailureCount <= 2)
                {
                    unknownFailureCount += 1;
                    ModBase.Log(ex, $"正版验证轮询第 {unknownFailureCount} 次失败");
                    ModBase.Log(ex.Message);
                    await Task.Delay(2000).ConfigureAwait(false);
                }
                else
                {
                    Finished(new Exception(Lang.Text("Launch.Account.LoginDialog.PollingFailed"), ex));
                    return;
                }
            }
        }
    }


    #region 弹窗

    private readonly ModMain.MyMsgBoxConverter myConverter;
    private readonly int uuid = ModBase.GetUuid();

    public MyMsgLogin(ModMain.MyMsgBoxConverter converter)
    {
        try
        {
            InitializeComponent();
            Btn1.Name += ModBase.GetUuid();
            Btn2.Name += ModBase.GetUuid();
            Btn3.Name += ModBase.GetUuid();
            myConverter = converter;
            ShapeLine.StrokeThickness = ModBase.GetWPFSize(1d);
            data = (JsonObject)converter.Content;
            oAuthUrl = converter.AuthUrl?.ToString() ?? "";
            Init();
        }
        catch (Exception ex)
        {
            ModBase.Log(
                ex,
                Lang.Text("Launch.Account.LoginDialog.Error.Init"),
                ModBase.LogLevel.Hint,
                userSummary: Lang.Text("Launch.Account.LoginDialog.Error.Init"));
        }

        Loaded += Load;
    }

    private void Load(object sender, EventArgs e)
    {
        try
        {
            // 动画
            Opacity = 0d;
            ModAnimation.AniStart(
                ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground, BlurBorder.BackgroundProperty,
                    (myConverter.IsWarn
                        ? new ModBase.MyColor(140d, 80d, 0d, 0d)
                        : new ModBase.MyColor(90d, 0d, 0d, 0d)) - ModMain.frmMain.PanMsgBackground.Background, 200),
                "PanMsgBackground Background");
            ModAnimation.AniStart(
                new[]
                {
                    ModAnimation.AaOpacity(this, 1d, 120, 60),
                    ModAnimation.AaDouble(i => TransformPos.Y += (double)i,
                        -TransformPos.Y, 300, 60, new ModAnimation.AniEaseOutBack(ModAnimation.AniEasePower.Weak)),
                    ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
                        -TransformRotate.Angle, 300, 60,
                        new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak))
                }, "MyMsgBox " + uuid);
            // 记录日志
            ModBase.Log($"[Control] 正版验证弹窗：{LabTitle.Text}\r\n{LabCaption.Text}");
        }
        catch (Exception ex)
        {
            ModBase.Log(
                ex,
                Lang.Text("Launch.Account.LoginDialog.Error.Load"),
                ModBase.LogLevel.Hint,
                userSummary: Lang.Text("Launch.Account.LoginDialog.Error.Load"));
        }
    }

    private void Close()
    {
        // 动画
        ModAnimation.AniStart(new[]
        {
            ModAnimation.AaCode(() =>
            {
                if (!ModMain.WaitingMyMsgBox.Any())
                    ModAnimation.AniStart(ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground,
                        BlurBorder.BackgroundProperty,
                        new ModBase.MyColor(0d, 0d, 0d, 0d) - ModMain.frmMain.PanMsgBackground.Background, 200,
                        ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak)));
            }, 30),
            ModAnimation.AaOpacity(this, -Opacity, 80, 20),
            ModAnimation.AaDouble(i => TransformPos.Y += (double)i, 20d - TransformPos.Y,
                150, 0, new ModAnimation.AniEaseOutFluent()),
            ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
                6d - TransformRotate.Angle, 150, 0, new ModAnimation.AniEaseInFluent(ModAnimation.AniEasePower.Weak)),
            ModAnimation.AaCode(() => ((Grid)Parent).Children.Remove(this), after: true)
        }, "MyMsgBox " + uuid);
    }

    // 实现回车和 Esc 的接口（#4857）
    public void Btn1_Click(object sender, MouseButtonEventArgs e)
    {
    }

    public void Btn3_Click(object sender, MouseButtonEventArgs e)
    {
        Finished(new ThreadInterruptedException());
    }

    private void Drag(object sender, MouseButtonEventArgs e)
    {
        // On Error Resume Next
        if (e.GetPosition(ShapeLine).Y <= 2d)
            ModMain.frmMain.DragMove();
    }

    #endregion
}