using Noctalk.Shared.Chat.Configuration;
using System.IO;
using System.Text;
using System.Text.Json;

namespace Noctalk_client.Client.Conversations;

public sealed class Conversation_repository
{
    private readonly string executableDirectory;

    public Conversation_repository(string The_executable_directory)
    {
        executableDirectory = The_executable_directory;
    }

    public List<Conversation_list_item> Conversations__load_all()
    {
        string chatsDirectory = Path.Combine(executableDirectory, "Data", "Chats");
        Directory.CreateDirectory(chatsDirectory);

        List<Conversation_list_item> conversations = [];

        foreach (string conversationDirectory in Directory.EnumerateDirectories(chatsDirectory))
        {
            string configPath = Path.Combine(conversationDirectory, "config.cfg");

            if (!File.Exists(configPath))
            {
                continue;
            }

            try
            {
                string encodedJson = File.ReadAllText(configPath, Encoding.UTF8);
                string json = Encoding.UTF8.GetString(Convert.FromBase64String(encodedJson));
                Conversation_config? conversationConfig = JsonSerializer.Deserialize<Conversation_config>(json);

                if (conversationConfig is not null && (Conversations__config__apply_legacy_nickname(conversationConfig, json) || Conversations__config__has_legacy_local_tor_port(json)))
                {
                    Conversations__config__write(configPath, conversationConfig);
                }

                if (conversationConfig is not null
                    && conversationConfig.conversation__guid != Guid.Empty
                    && conversationConfig.conversation__client__guid != Guid.Empty
                    && !string.IsNullOrWhiteSpace(conversationConfig.conversation__local_encryption__key)
                    && !string.IsNullOrWhiteSpace(conversationConfig.Server__onion_address))
                {
                    conversations.Add(new Conversation_list_item
                    {
                        Conversation_config = conversationConfig,
                        Config_path = configPath
                    });
                }
            }
            catch
            {
                // Bad conversation configs are ignored so one corrupt file does not block startup.
            }
        }

        return conversations.OrderBy(The_conversation => The_conversation.ToString()).ToList();
    }

    public void Conversations__delete(Conversation_list_item The_conversation)
    {
        string? conversationDirectory = Path.GetDirectoryName(The_conversation.Config_path);

        if (!string.IsNullOrWhiteSpace(conversationDirectory) && Directory.Exists(conversationDirectory))
        {
            Directory.Delete(conversationDirectory, true);
        }
    }

    private static bool Conversations__config__apply_legacy_nickname(Conversation_config The_conversation_config, string The_json)
    {
        if (!string.IsNullOrWhiteSpace(The_conversation_config.Peer__nickname))
        {
            return false;
        }

        using JsonDocument document = JsonDocument.Parse(The_json);
        if (!document.RootElement.TryGetProperty("Nickname", out JsonElement legacyNicknameElement))
        {
            return false;
        }

        string? legacyNickname = legacyNicknameElement.GetString();
        if (string.IsNullOrWhiteSpace(legacyNickname))
        {
            return false;
        }

        The_conversation_config.Peer__nickname = legacyNickname;
        return true;
    }

    private static bool Conversations__config__has_legacy_local_tor_port(string The_json)
    {
        using JsonDocument document = JsonDocument.Parse(The_json);
        return document.RootElement.TryGetProperty("Client__local_tor__port", out _);
    }

    private static void Conversations__config__write(string The_config_path, Conversation_config The_conversation_config)
    {
        string json = JsonSerializer.Serialize(The_conversation_config, new JsonSerializerOptions { WriteIndented = true });
        string encodedJson = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
        File.WriteAllText(The_config_path, encodedJson, Encoding.UTF8);
    }
}
