@page "/chat"
@page "/chat/{InitialSessionId}"
@rendermode InteractiveServer
@inject IChatSessionService ChatSessionService
@inject NavigationManager NavigationManager
@using Alchegos.HCI.Models
@using Alchegos.HCI.Services
@implements IAsyncDisposable

<PageTitle>Chat</PageTitle>

<h1>Chat Session</h1>

<div class="session-selector">
    <input @bind="currentSessionIdInput" placeholder="Enter or Generate Session ID" />
    <button @onclick="LoadSession" disabled="@isLoading">Load / Start Session</button>
    <button @onclick="GenerateSessionId" disabled="@isLoading">Generate New ID</button>
    <input @bind="externalWebhookUrl" placeholder="Server url">
    @if (!string.IsNullOrEmpty(activeSessionId))
    {
        <span>Active Session: @activeSessionId</span>
    }
</div>

@if (isLoading)
{
    <p><em>Loading session...</em></p>
}
else if (currentSession != null)
{
    <div class="chat-history" style="height: 400px; overflow-y: scroll; border: 1px solid #ccc; margin-bottom: 10px; padding: 5px;">
        @foreach (var message in currentSession.Messages)
        {
            <div class="@(message.IsUser ? "user-message" : "server-message")">
                <strong>@(message.IsUser ? "You" : "Server"):</strong>
                <span>@message.Content</span>
                <small style="font-size: 0.7em; color: grey; display: block;">@message.Timestamp.ToLocalTime()</small>
            </div>
        }
        @if (currentSession.IsWaitingForResponse)
        {
             <p><em>Waiting for response...</em></p>
        }
    </div>

    <div class="chat-input">
        <input @bind="newMessage" placeholder="Type your message..." @onkeydown="HandleKeyDown" disabled="@currentSession.IsWaitingForResponse" />
        <button @onclick="SendMessage" disabled="@(currentSession.IsWaitingForResponse || string.IsNullOrWhiteSpace(newMessage))">Send</button>
    </div>
}
else if (sessionLoadAttempted)
{
     <p><em>Enter a Session ID and click "Load / Start Session" or generate a new one.</em></p>
}


@code {
    [Parameter] public string? InitialSessionId { get; set; }

    private string currentSessionIdInput { get; set; } = string.Empty;
    private string activeSessionId { get; set; } = string.Empty;
    private ChatSession? currentSession;
    private string newMessage { get; set; } = string.Empty;
    private bool isLoading = false;
    private bool sessionLoadAttempted = false;
    private string externalWebhookUrl { get; set; } = string.Empty;


    private string? _previousSessionId = null;

    protected override async Task OnParametersSetAsync()
    {
        Console.WriteLine($"--- OnParametersSetAsync START. InitialSessionId: {InitialSessionId} ---");
        if (InitialSessionId != _previousSessionId && !string.IsNullOrEmpty(InitialSessionId))
        {
            isLoading = true;
            sessionLoadAttempted = true;

            if (!string.IsNullOrEmpty(_previousSessionId) && _previousSessionId != InitialSessionId)
            {
                Console.WriteLine($"Parameter changed from {_previousSessionId} to {InitialSessionId}. Unregistering old callbacks for {_previousSessionId}.");
                var oldId = _previousSessionId;
                _ = Task.Run(() => ChatSessionService.UnregisterSessionCallbacks(oldId)); 
            }


            activeSessionId = InitialSessionId;
            _previousSessionId = InitialSessionId;

            Console.WriteLine($"Loading session from parameter: {activeSessionId}");
            currentSession = ChatSessionService.GetOrCreateSession(activeSessionId); 

            if (currentSession != null)
            {
                Console.WriteLine($"Session obtained: {currentSession.SessionId}");
                await RegisterCallbacksAsync(); 
            }
            else
                Console.WriteLine("!!! Failed to get/create session in OnParametersSetAsync!");
            


            isLoading = false;
            Console.WriteLine("--- OnParametersSetAsync END. isLoading set to false ---");
            
        }
        else if (string.IsNullOrEmpty(InitialSessionId) && _previousSessionId != null)
        {
            Console.WriteLine("--- OnParametersSetAsync: InitialSessionId became null/empty. Clearing session. ---");
            await UnregisterCallbacksAsync();
            currentSession = null;
            activeSessionId = string.Empty;
            _previousSessionId = null;
            currentSessionIdInput = string.Empty;
            sessionLoadAttempted = false;
        }
        else if (InitialSessionId == _previousSessionId)
        {
            Console.WriteLine($"--- OnParametersSetAsync: InitialSessionId '{InitialSessionId}' did not change. Skipping load. ---");
        }
        else
        {
            Console.WriteLine($"--- OnParametersSetAsync: InitialSessionId '{InitialSessionId}' is null/empty and no previous ID. Initial state. ---");
        }
    }

    protected override void OnInitialized()
    {
        if (!string.IsNullOrEmpty(InitialSessionId))
            currentSessionIdInput = InitialSessionId;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && !string.IsNullOrEmpty(activeSessionId))
            await RegisterCallbacksAsync();
    }


    private void GenerateSessionId()
    {
        var newId = Guid.NewGuid().ToString("N");
        currentSessionIdInput = newId;
        Console.WriteLine($"--- GenerateSessionId: Generated {newId}, Navigating... ---");
        NavigationManager.NavigateTo($"/chat/{newId}"); 
    }

    private void LoadSession()
    {
        if (string.IsNullOrWhiteSpace(currentSessionIdInput))
        {
            Console.WriteLine("--- LoadSession Clicked: Input empty, doing nothing. ---");
            return;
        }

        var sessionIdToLoad = currentSessionIdInput;
        var targetUrl = $"/chat/{sessionIdToLoad}";
        string currentPathAndQuery = new Uri(NavigationManager.Uri).PathAndQuery;
        
        if (!currentPathAndQuery.Equals(targetUrl, StringComparison.OrdinalIgnoreCase))
        {
            Console.WriteLine($"--- LoadSession Clicked: Navigating to {targetUrl}... ---");
            NavigationManager.NavigateTo(targetUrl);
        }
        else
        {
            Console.WriteLine($"--- LoadSession Clicked: Already at {targetUrl}. No navigation needed. ---");
        }
    }


    private async Task SendMessage()
    {
        if (currentSession == null || string.IsNullOrWhiteSpace(newMessage) || currentSession.IsWaitingForResponse || String.IsNullOrWhiteSpace(externalWebhookUrl))
            return;

        var userMessage = new ChatMessage { IsUser = true, Content = newMessage };
        ChatSessionService.AddMessage(activeSessionId, userMessage);
        ChatSessionService.SetWaitingStatus(activeSessionId, true);

        var messageToSend = newMessage;
        newMessage = string.Empty;

        StateHasChanged();

        await ChatSessionService.SendMessageToExternalWebhook(externalWebhookUrl, activeSessionId, messageToSend);

    }

    private async Task HandleKeyDown(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && !currentSession.IsWaitingForResponse && !string.IsNullOrWhiteSpace(newMessage))
            await SendMessage();
    }


    [JSInvokable]
    public async Task HandleMessageReceived(ChatMessage message)
    {
        await InvokeAsync(StateHasChanged);
    }

    [JSInvokable]
    public async Task HandleSessionClosed()
    {
        await InvokeAsync(() =>
        {
            if (currentSession != null && currentSession.SessionId == activeSessionId)
            {
                Console.WriteLine($"UI notified session closed: {activeSessionId}");
                currentSession = null;
                activeSessionId = string.Empty;
                currentSessionIdInput = string.Empty;
                NavigationManager.NavigateTo("/chat", forceLoad: false);
                StateHasChanged();
            }
        });
    }

    private async Task RegisterCallbacksAsync()
    {
        if (currentSession != null)
        {
            _ = Task.Run(() =>
            {
                ChatSessionService.RegisterSessionCallbacks(
                    currentSession.SessionId,
                    HandleMessageReceived,
                    HandleSessionClosed
                );
            });
            await Task.CompletedTask;
        }
    }

    private async Task UnregisterCallbacksAsync()
    {
        if (!string.IsNullOrEmpty(activeSessionId))
        {
            var capturedSessionId = activeSessionId;
            _ = Task.Run(() => ChatSessionService.UnregisterSessionCallbacks(capturedSessionId));
            await Task.CompletedTask;
        }
    }

    public async ValueTask DisposeAsync()
    {
        await UnregisterCallbacksAsync();
    }

}