// Copyright (c) Barry Dorrans. All rights reserved.
// Licensed under the MIT License.

using System.Diagnostics;

using idunno.AtProto;
using idunno.Bluesky;

using Microsoft.Extensions.Logging;

using Samples.Common;

namespace Samples.Bookmarks;

public sealed class Program
{
    static async Task<int> Main(string[] args)
    {
        // Necessary to render emojis.
        Console.OutputEncoding = System.Text.Encoding.UTF8;

        var parser = Helpers.ConfigureCommandLine(
            args,
            "BlueskyAgent Bookmarks Sample",
            PerformOperations);

        return await parser.InvokeAsync();
    }

    static async Task PerformOperations(string? userHandle, string? password, string? authCode, Uri? proxyUri, CancellationToken cancellationToken = default)
    {
        ArgumentException.ThrowIfNullOrEmpty(userHandle);
        ArgumentException.ThrowIfNullOrEmpty(password);

        // Uncomment the next line to route all requests through Fiddler Everywhere
        proxyUri = new Uri("http://localhost:8866");

        // Uncomment the next line to route all requests  through Fiddler Classic
        // proxyUri = new Uri("http://localhost:8888");

        // Change the log level in the ConfigureConsoleLogging() to enable logging
        using (ILoggerFactory? loggerFactory = Helpers.ConfigureConsoleLogging(LogLevel.Debug))

        // Create a new BlueSkyAgent
        using (var agent = new BlueskyAgent(
            options: new BlueskyAgentOptions()
            {
                LoggerFactory = loggerFactory,

                HttpClientOptions = new HttpClientOptions()
                {
                    ProxyUri = proxyUri
                },
            }))
        {
            // Delete if your test code does not require authentication
            // START-AUTHENTICATION
            var loginResult = await agent.Login(userHandle, password, authCode, cancellationToken: cancellationToken);
            if (!loginResult.Succeeded)
            {
                if (loginResult.AtErrorDetail is not null &&
                    string.Equals(loginResult.AtErrorDetail.Error!, "AuthFactorTokenRequired", StringComparison.OrdinalIgnoreCase))
                {
                    ConsoleColor oldColor = Console.ForegroundColor;

                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Login requires an authentication code.");
                    Console.WriteLine("Check your email and use --authCode to specify the authentication code.");
                    Console.ForegroundColor = oldColor;

                    return;
                }
                else
                {
                    ConsoleColor oldColor = Console.ForegroundColor;

                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Login failed.");
                    Console.ForegroundColor = oldColor;

                    if (loginResult.AtErrorDetail is not null)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;

                        Console.WriteLine($"Server returned {loginResult.AtErrorDetail.Error} / {loginResult.AtErrorDetail.Message}");
                        Console.ForegroundColor = oldColor;

                        return;
                    }
                }
            }
            // END-AUTHENTICATION

            var testPostResult = await agent.Post("Test post, for bookmarking", cancellationToken: cancellationToken);
            testPostResult.EnsureSucceeded();

            var createBookmarkResult = await agent.CreateBookmark(testPostResult.Result.StrongReference, cancellationToken: cancellationToken);
            createBookmarkResult.EnsureSucceeded();
            Debugger.Break();

            var getPostResult = await agent.GetPost(testPostResult.Result.StrongReference.Uri, cancellationToken: cancellationToken);
            getPostResult.EnsureSucceeded();
            Console.WriteLine($"Test post has been bookmarked {getPostResult.Result.BookmarkCount} time(s).");
            Debugger.Break();

            var deleteBookmarkResult = await agent.DeleteBookmark(testPostResult.Result.StrongReference.Uri, cancellationToken: cancellationToken);
            createBookmarkResult.EnsureSucceeded();
            Debugger.Break();

            getPostResult = await agent.GetPost(testPostResult.Result.StrongReference.Uri, cancellationToken: cancellationToken);
            getPostResult.EnsureSucceeded();
            Console.WriteLine($"Test post has been bookmarked {getPostResult.Result.BookmarkCount} time(s).");
            Debugger.Break();
        }
    }
}