using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Controls.Primitives;
using Sonex.DBWrapper;
using System;
using System.Security;
using System.Threading.Tasks;
using Windows.Networking;
using static System.Net.Mime.MediaTypeNames;

namespace Sonex.Client.Models;

public partial class AccountModel : ObservableObject
{
    [ObservableProperty]
    private int id;

    [ObservableProperty]
    private string accountName = string.Empty;

    [ObservableProperty]
    private string? firstName;

    [ObservableProperty]
    private string? lastName;

    public string FullName => $"{FirstName} {LastName}".Trim();

    [ObservableProperty]
    private string? email;

    [ObservableProperty]
    private string? phoneNumber;

    [ObservableProperty]
    private string? department;

    [ObservableProperty]
    private string? jobTitle;

    [ObservableProperty]
    private string? accountLocusWms;

    [ObservableProperty]
    private string? accountLocusTerminal;

    [ObservableProperty]
    private DateTime? createdAt;

    [ObservableProperty]
    private bool superadmin;

    public string CreatedAtText => CreatedAt.HasValue
        ? CreatedAt.Value.ToString("yyyy-MM-dd HH:mm:ss")
        : "";

    [ObservableProperty]
    private DateTime? updatedAt;

    public string UpdatedAtText => UpdatedAt.HasValue
        ? UpdatedAt.Value.ToString("yyyy-MM-dd HH:mm:ss")
        : "";

    [ObservableProperty]
    private bool isEnabled;

    [ObservableProperty]
    private string[] groups = [];

    [ObservableProperty]
    private string[] grantedPermissions = [];


    public double Opacity => IsEnabled ? 1d : 0.4d;

    partial void OnFirstNameChanged(string? value) => OnPropertyChanged(nameof(FullName));
    partial void OnLastNameChanged(string? value) => OnPropertyChanged(nameof(FullName));
    partial void OnCreatedAtChanged(DateTime? value) => OnPropertyChanged(nameof(CreatedAtText));
    partial void OnUpdatedAtChanged(DateTime? value) => OnPropertyChanged(nameof(UpdatedAtText));
    partial void OnIsEnabledChanged(bool value) => OnPropertyChanged(nameof(Opacity));

    public static Task<DB.SingleResult<bool>> ChangePassword(string accountName, string password)
    {
        return DB.QuerySingleAsync<bool>(
            "SELECT sonex.accounts_password_change(@AccountName, @Password);",
            new
            {
                AccountName = accountName,
                Password = password
            });
    }

    public static Task<DB.SingleResult<bool>> Disable(string accountName)
    {
        return DB.QuerySingleAsync<bool>(
            "SELECT sonex.accounts_disable(@AccountName);",
            new
            {
                AccountName = accountName,
            });
    }

    public static Task<DB.SingleResult<bool>> Enable(string accountName)
    {
        return DB.QuerySingleAsync<bool>(
            "SELECT sonex.accounts_enable(@AccountName);",
            new
            {
                AccountName = accountName,
            });
    }

    public static Task<DB.SingleResult<bool>> SetSuperAdmin(string accountName, bool value)
    {
        return DB.QuerySingleAsync<bool>(
            "SELECT sonex.accounts_access_superadmin(@AccountName, @Value);",
            new
            {
                AccountName = accountName, Value = value
            });
    }

    public static Task<DB.SingleResult<AccountModel>> Get(string accountName)
    {
        return DB.QuerySingleAsync<AccountModel>("SELECT * FROM sonex.v_accounts_groups WHERE account_name = @account_name LIMIT 1;",
            new { account_name = accountName });
    }
    public static Task<DB.SingleResult<AccountModel>> GetCurrentUser()
    {
        return DB.QuerySingleAsync<AccountModel>("SELECT * FROM sonex.current_account_group_get();");
    }
    public static Task<DB.Result<AccountModel>> GetAll()
    {
        return DB.QueryListAsync<AccountModel>("SELECT * FROM sonex.v_accounts_groups;");
    }

    public static Task<DB.SingleResult<bool>> UpdatePersonalInformation(AccountModel selectedAccount)
    {
        return DB.QuerySingleAsync<bool>("UPDATE sonex.accounts SET first_name = @FirstName, last_name = @LastName, department = @Department, updated_at = NOW() WHERE account_name = @AccountName RETURNING TRUE;", 
            new { AccountName = selectedAccount.AccountName, FirstName = selectedAccount.FirstName, LastName = selectedAccount.LastName, Department = selectedAccount.Department });
    }

    public static Task<DB.SingleResult<bool>> UpdateLinkedAccounts(AccountModel selectedAccount)
    {
        return DB.QuerySingleAsync<bool>("UPDATE sonex.accounts SET account_locus_wms = @AccountLocusWms, account_locus_terminal = @AccountLocusTerminal, updated_at = NOW() WHERE account_name = @AccountName RETURNING TRUE;", 
            new { AccountName = selectedAccount.AccountName, AccountLocusWms = selectedAccount.AccountLocusWms, AccountLocusTerminal = selectedAccount.AccountLocusTerminal});
    }

    public static Task<DB.SingleResult<bool>> AddPermission(string accountName, string permission)
    {
        return DB.QuerySingleAsync<bool>("SELECT sonex.accounts_access_add(@AccountName, @Permission);",
            new { AccountName = accountName, Permission = permission});
    }

    public static Task<DB.SingleResult<bool>> RemovePermission(string accountName, string permission)
    {
        return DB.QuerySingleAsync<bool>("SELECT sonex.accounts_access_remove(@AccountName, @Permission);",
            new { AccountName = accountName, Permission = permission });
    }

    public static Task<DB.SingleResult<int>> Create(string firstName, string lastname, string accountName, string password)
    {
        return DB.QuerySingleAsync<int>("SELECT sonex.accounts_create(@AccountName, @Password, @FirstName, @Lastname); ",
        new { AccountName = accountName, Password = password, FirstName = firstName, Lastname = lastname });
    }

    public static Task<DB.SingleResult<bool>> Delete(string accountName)
    {
        return DB.QuerySingleAsync<bool>("SELECT sonex.accounts_delete(@AccountName); ",
        new { AccountName = accountName});
    }
}
