using SurrealDb.Net;
using SurrealDb.Net.Models.Auth;
using System.Text.Json;
using System;
using System.Net;
using System.Threading.Tasks;
using System.Text;
using System.Text.Json;

using RelayCore.Enums;
using RelayCore.Models;


await using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc");
await db.SignIn(new RootAuth { Username = "root", Password = "secret" });
await db.Use("test", "test");

var keeper = await CreateUserAsync(db, "Keeper317", "Keeper317@gmail.com", "password");
var kira = await CreateUserAsync(db, "Ru_Kira", "jduesling13@gmail.com", "password");
var test = await CreateUserAsync(db, "Test", "test@gmail.com", "password");

var server = new Program();

Console.WriteLine($"Keeper created: {ToJsonString(keeper)}");
Console.WriteLine($"Kira created: {ToJsonString(kira)}");
Console.WriteLine($"Test created: {ToJsonString(test)}");

await server.Main(db);
Console.ReadKey(true);
return;

static string ToJsonString(object? o)
{
    return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true });
}

static async Task<Users> CreateUserAsync(SurrealDbClient db, string username, string email, string rawPassword)
{
    var now = DateTime.UtcNow;

    var user = new Users
    {
        Username = username,
        Email = email,
        CreatedAt = now,
        UpdatedAt = now,
        LastLogin = now,
        TwoFactorEnabled = false,
        EmailVerified = false,
        AccountStatus = (int)AccountStatuses.Active,
        OnlineStatus = (int)OnlineStatuses.Online,
    };

    var created = await db.Create("users", user);

    var hasher = new PasswordHasher();
    var passwordHash = hasher.HashPassword(created.Id.ToString() + rawPassword);

    var updated = await db.Merge<PasswordHash, Users>(new PasswordHash
    {
        Id = created.Id,
        Password = passwordHash
    });

    return updated;
}


partial class Program
{
    public async Task Main(SurrealDbClient db)
    {
        // Set up listener
        using var listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8080/");
        listener.Start();
        Console.WriteLine("API Started: http://localhost:8080/");

        while (true)
        {
            // Process requests
            var context = await listener.GetContextAsync();
            var req = context.Request;
            var res = context.Response;

            if (req.Url.AbsolutePath == "/api/hello" && req.HttpMethod == "GET")
            {
                var data = new { Message = "Hello, world!", Time = DateTime.Now };
                byte[] buf = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(data));
                res.ContentType = "application/json";
                await res.OutputStream.WriteAsync(buf, 0, buf.Length);
            }

            if (req.Url.AbsolutePath == "/api/users" && req.HttpMethod == "GET")
            {
                var data = new { Message = GetDBUsers(db).Result, Time = DateTime.Now };
                byte[] buf = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(data));
                res.ContentType = "application/json";
                await res.OutputStream.WriteAsync(buf, 0, buf.Length);
            }
            res.Close();
        }
    }
    static async Task<Users[]> GetDBUsers(SurrealDbClient db)
     {
         var users = await db.Select<Users>("users");
         Console.WriteLine(ToJsonString(users));
         return users.ToArray();
     }
    static string ToJsonString(object? o)
    {
        return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true, });
    }
}