using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper;
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.ActionDispatcher;
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.SystemActions;
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.SwitchControlActions;

var builder = WebApplication.CreateBuilder(args);

// GeViServer connection state
GeViDatabase? database = null;
string? currentAddress = null;
string? currentUsername = null;
List<string> receivedMessages = new List<string>();

var app = builder.Build();

// Event handler for received messages
void OnDatabaseNotification(object? sender, GeViSoftDatabaseNotificationEventArgs e)
{
    var msg = $"[{DateTime.Now:HH:mm:ss}] Notification: {e.ServerNotificationType}";
    Console.WriteLine(msg);
    receivedMessages.Add(msg);
}

void OnReceivedCustomAction(object? sender, GeViAct_CustomActionEventArgs e)
{
    var msg = $"[{DateTime.Now:HH:mm:ss}] CustomAction({e.aCustomInt}, \"{e.aCustomText}\")";
    Console.WriteLine(msg);
    receivedMessages.Add(msg);
}

void OnReceivedCrossSwitch(object? sender, GeViAct_CrossSwitchEventArgs e)
{
    var msg = $"[{DateTime.Now:HH:mm:ss}] CrossSwitch({e.aVideoInput}, {e.aVideoOutput}, {e.aSwitchMode})";
    Console.WriteLine(msg);
    receivedMessages.Add(msg);
}

// Connection endpoint
app.MapPost("/connect", (ConnectRequest request) =>
{
    try
    {
        // Create and configure database connection
        database = new GeViDatabase();
        database.Create(
            request.Address,
            request.Username,
            request.Password
        );

        // Register event handlers BEFORE connecting
        database.DatabaseNotification += OnDatabaseNotification;
        database.ReceivedCustomAction += OnReceivedCustomAction;
        database.ReceivedCrossSwitch += OnReceivedCrossSwitch;
        database.RegisterCallback();

        // Connect to GeViServer
        var connectResult = database.Connect();

        if (connectResult == GeViConnectResult.connectOk)
        {
            currentAddress = request.Address;
            currentUsername = request.Username;
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Connected to GeViServer at {request.Address}");

            return Results.Ok(new
            {
                success = true,
                message = "Connected to GeViServer",
                address = request.Address,
                username = request.Username,
                connected_at = DateTime.UtcNow
            });
        }
        else
        {
            return Results.BadRequest(new
            {
                error = "Connection failed",
                message = connectResult.ToString()
            });
        }
    }
    catch (Exception ex)
    {
        return Results.BadRequest(new
        {
            error = "Internal Server Error",
            message = ex.Message,
            stack_trace = ex.StackTrace
        });
    }
});

// Disconnect endpoint
app.MapPost("/disconnect", () =>
{
    try
    {
        if (database != null)
        {
            database.Disconnect();
            database.Dispose();
            database = null;
        }

        currentAddress = null;
        currentUsername = null;

        return Results.Ok(new
        {
            success = true,
            message = "Disconnected successfully"
        });
    }
    catch (Exception ex)
    {
        return Results.BadRequest(new
        {
            error = "Internal Server Error",
            message = ex.Message
        });
    }
});

// Status endpoint
app.MapGet("/status", () =>
{
    return Results.Ok(new
    {
        is_connected = database != null,
        address = currentAddress,
        username = currentUsername
    });
});

// Ping endpoint
app.MapPost("/ping", () =>
{
    try
    {
        if (database == null)
        {
            return Results.BadRequest(new { error = "Not connected" });
        }

        var result = database.SendPing();

        return Results.Ok(new
        {
            success = result,
            message = result ? "Ping successful" : "Ping failed"
        });
    }
    catch (Exception ex)
    {
        return Results.BadRequest(new
        {
            error = "Internal Server Error",
            message = ex.Message
        });
    }
});

// Send message endpoint
app.MapPost("/send-message", (SendMessageRequest request) =>
{
    try
    {
        if (database == null)
        {
            return Results.BadRequest(new { error = "Not connected" });
        }

        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] SENDING: {request.Message}");

        // Send action message
        database.SendMessage(request.Message);

        var logMsg = $"[{DateTime.Now:HH:mm:ss}] SENT: {request.Message}";
        receivedMessages.Add(logMsg);

        return Results.Ok(new
        {
            success = true,
            message = "Message sent successfully",
            sent_message = request.Message
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}");
        return Results.BadRequest(new
        {
            error = "Internal Server Error",
            message = ex.Message
        });
    }
});

// Get message log endpoint
app.MapGet("/messages", () =>
{
    return Results.Ok(new
    {
        count = receivedMessages.Count,
        messages = receivedMessages.TakeLast(50).ToList()
    });
});

// Clear message log endpoint
app.MapPost("/messages/clear", () =>
{
    receivedMessages.Clear();
    return Results.Ok(new { message = "Message log cleared" });
});

Console.WriteLine("========================================");
Console.WriteLine("GeViServer Bridge starting on port 7710");
Console.WriteLine("========================================");

// Run on port 7710 (avoiding conflict with GeViServer DevicePort 7701)
app.Run("http://localhost:7710");

// Request models
record ConnectRequest(
    string Address,
    string Username,
    string Password
);

record SendMessageRequest(string Message);
