using IWS5.Core.Enums;
using IWS5.Core.Models.Processing;
using IWS5.Server.DataAccess;
using Microsoft.Data.SqlClient;
using ILogger = Serilog.ILogger;

namespace IWS5.Server.EventProcessors;

public class QueueProcessor(ILogger logger, IConfiguration configuration) : EventProcessor(logger, configuration)
{
    public override async Task<bool> ProcessEventAsync(EventModel eventData, int processId)
    {
        Logger.Information(
            "Starting queue event processing for WorkItemId: {WorkItemId}, EventId: {EventId}, ProcessId: {ProcessId}, SourceQueueId: {SourceQueueId}, ServerRequest: {ServerRequest}",
            eventData.WorkItemId, eventData.CurrentEventId, processId, eventData.SourceQueueId,
            eventData.ServerRequest);

        await using (var sqlConnection = new SqlConnection(ConnectionString))
        {
            try
            {
                await sqlConnection.OpenAsync();
                
                Logger.Debug("Retrieving source queue event ID for SourceQueueId: {SourceQueueId}",
                    eventData.SourceQueueId);
                var sourceQueueEventId = eventData.SourceQueueId.HasValue
                    ? Repository.GetQueueEventId(sqlConnection, eventData.SourceQueueId.Value)
                    : 0;
                Logger.Debug("Source queue event ID: {SourceQueueEventId}", sourceQueueEventId);

                var cmd2 = new SqlCommand("", sqlConnection);
                string sqlStr;

                if (eventData.ServerRequest == ServerRequest.ForwardExistingWorkItem)
                {
                    Logger.Debug("Processing ForwardExistingWorkItem request");

                    if (sourceQueueEventId != eventData.CurrentEventId)
                    {
                        Logger.Debug(
                            "Moving work item to new queue (SourceQueueEventId: {SourceQueueEventId} != CurrentEventId: {CurrentEventId})",
                            sourceQueueEventId, eventData.CurrentEventId);

                        sqlStr =
                            "Update ATWorkItemReference SET QueueId = (SELECT Id FROM ATQueue WHERE EventId = @currentEventId), ServerRequest = 0, ServerRequestParam = NULL, LastActionDate = @currentDate WHERE WorkItemID = @workItemId";
                        cmd2.CommandText = sqlStr;
                        cmd2.Parameters.AddWithValue("@currentEventId", eventData.CurrentEventId);
                        cmd2.Parameters.AddWithValue("@currentDate", DateTime.Now);
                        cmd2.Parameters.AddWithValue("@workItemId", eventData.WorkItemId);

                        Logger.Information("Work item will be moved to queue for EventId: {CurrentEventId}",
                            eventData.CurrentEventId);
                    }
                    else
                    {
                        Logger.Debug(
                            "Queue unchanged (SourceQueueEventId: {SourceQueueEventId} == CurrentEventId: {CurrentEventId}), moving to next event",
                            sourceQueueEventId, eventData.CurrentEventId);

                        sqlStr =
                            "Update ATWorkItemReference SET QueueId = NULL, EventID = @nextEventId, ServerRequestParam = NULL, LastActionDate = @currentDate WHERE WorkItemID = @workItemId";
                        cmd2.CommandText = sqlStr;
                        cmd2.Parameters.AddWithValue("@nextEventId", eventData.NextEventId);
                        cmd2.Parameters.AddWithValue("@currentDate", DateTime.Now);
                        cmd2.Parameters.AddWithValue("@workItemId", eventData.WorkItemId);

                        Logger.Information("Work item will move to next event: {NextEventId}", eventData.NextEventId);
                    }
                }
                else
                {
                    Logger.Warning("Unexpected ServerRequest type: {ServerRequest} for WorkItemId: {WorkItemId}",
                        eventData.ServerRequest, eventData.WorkItemId);
                    return false;
                }

                Logger.Debug("Executing queue update query: {SqlQuery}", sqlStr);
                int rowsAffected = await cmd2.ExecuteNonQueryAsync();

                if (rowsAffected == 0)
                {
                    Logger.Warning("No rows affected when updating work item reference for WorkItemId: {WorkItemId}",
                        eventData.WorkItemId);
                }
                else
                {
                    Logger.Debug("Successfully updated {RowsAffected} work item reference(s)", rowsAffected);
                }

                Logger.Information("Successfully completed queue processing for WorkItemId: {WorkItemId}",
                    eventData.WorkItemId);
                return true;
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error in queue processing for WorkItemId: {WorkItemId}, EventId: {EventId}",
                    eventData.WorkItemId, eventData.CurrentEventId);
                return false;
            }
        }
    }
}