using Blahblah.FlowerApp.Data;
using Blahblah.FlowerApp.Data.Model;
using Microsoft.Extensions.Logging;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using static Blahblah.FlowerApp.Extensions;

namespace Blahblah.FlowerApp;

public partial class LoginPage : AppContentPage
{
    static readonly BindableProperty UserIdProperty = CreateProperty<string, LoginPage>(nameof(UserId));
    static readonly BindableProperty PasswordProperty = CreateProperty<string, LoginPage>(nameof(Password));
    static readonly BindableProperty ErrorMessageProperty = CreateProperty<string?, LoginPage>(nameof(ErrorMessage));

    public string UserId
    {
        get => (string)GetValue(UserIdProperty);
        set => SetValue(UserIdProperty, value);
    }
    public string Password
    {
        get => (string)GetValue(PasswordProperty);
        set => SetValue(PasswordProperty, value);
    }
    public string? ErrorMessage
    {
        get => (string?)GetValue(ErrorMessageProperty);
        set => SetValue(ErrorMessageProperty, value);
    }

    public event EventHandler<UserItem>? AfterLogined;

    public LoginPage(FlowerDatabase database, ILogger logger) : base(database, logger)
    {
        InitializeComponent();
    }

    private async void Login_Clicked(object sender, EventArgs e)
    {
        var userId = UserId;
        var password = Password;
        if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(password))
        {
            ErrorMessage = L("idPasswordRequired", "User id and password is required.");
            return;
        }

        IsEnabled = false;
        ErrorMessage = null;
        await Loading(true);

        var user = await Task.Run(() => DoLogin(userId, password));

        if (user == null)
        {
            await Loading(false);
            IsEnabled = true;
        }
        else
        {
            AppResources.SetUser(user);
            var count = await Database.SetUser(user);
            if (count <= 0)
            {
                this.LogWarning($"failed to save user item, with user: {user}");
            }
            AfterLogined?.Invoke(this, user);
        }
    }

    private async Task<UserItem?> DoLogin(string userId, string password)
    {
        try
        {
            using var client = new HttpClient();
            client.DefaultRequestHeaders.TryAddWithoutValidation("X-ClientAgent", Constants.UserAgent);
            using var response = await client.PostAsJsonAsync($"{Constants.BaseUrl}/api/user/auth", new LoginParameter(userId, password));
            if (response != null)
            {
                response.EnsureSuccessStatusCode();
                if (response.Headers.TryGetValues("Authorization", out var values) &&
                    values.FirstOrDefault() is string oAuth)
                {
                    Constants.SetAuthorization(oAuth);
                    var user = await response.Content.ReadFromJsonAsync<UserItem>();
                    if (user != null)
                    {
                        user.Token = oAuth;
                        return user;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //await this.AlertError(L("failedLogin", "Failed to login, please try again later."));
            ErrorMessage = L("failedLogin", "Failed to login, please try again later.");
            this.LogError(ex, $"error occurs in LoginPage, {ex.Message}");
        }
        return null;
    }

    record LoginParameter(string Id, string Password)
    {
        [JsonPropertyName("id")]
        public string Id { get; init; } = Id;

        [JsonPropertyName("password")]
        public string Password { get; init; } = Password;
    }
}