using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Dacryptero.DB.Creation;
using Dacryptero.Notifications;

namespace Dacryptero.Web.Events.Receive;

public class DatabaseAddFinish : ReceiveBase
{
    public string Id { get; private set; } = "";

    public override async Task Execute(ExecuteArgs args)
    {
        if (!args.Connection.NewDBInfo.TryGetValue(Id, out NewDBInfo? info))
        {
            args.SendNotification(Notification.Error(
                "Cannot create DB",
                "Creation Key not found"
            ));
            return;
        }

        var hash = System.Security.Cryptography.SHA512.HashData(info.MasterKey.Span);

        var config = new DB.DBConfig(
            info.Name,
            GetPath(
                Path.Combine(Config.Default.DB.BaseDir, info.Name)
            ),
            hash,
            info.Schema
        );
        config.Access.AddRange(info.Accesses);
        await config.SaveAsync().ConfigureAwait(false);

        var controller = args.Connection.DB.AddController(config);
        controller.Decrypt(info.MasterKey, true);

        args.Connection.Session.AddController(controller);

        await WebSocketConnection.Foreach(async con =>
        {
            await con.Send(new Send.InfoSend(con)).ConfigureAwait(false);
        }).ConfigureAwait(false);
        await args.Connection.Send(new Send.DatabaseCreated(info)).ConfigureAwait(false);
    }

    private string GetPath(string path)
    {
        if (!Directory.Exists(path))
            return path;
        var rng = new Random();
        Span<byte> buffer = stackalloc byte[4];
        while (true)
        {
            rng.NextBytes(buffer);
            var ext = $"{path}_{Convert.ToHexString(buffer)}";
            if (!Directory.Exists(ext))
                return ext;
        }
    }

    public override void ReadJsonContent(JsonElement json)
    {
        Id = json.GetProperty("id").GetString() ?? "";
    }
}