using System.Data;
using System.Text;
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 SetDataProcessor(ILogger logger, IConfiguration configuration) : EventProcessor(logger, configuration)
{
    public override async Task<bool> ProcessEventAsync(EventModel eventData, int processId)
    {
        try
        {
            using (var sqlConnection = new SqlConnection(ConnectionString))
            {
                await sqlConnection.OpenAsync();

                //Get the SetData records for the ProcessId and the EventId
                var sqlStr = $"Select * from ATSetData where processId = {processId} AND EventId = {eventData.CurrentEventId}";

                SqlDataAdapter dap3 = new SqlDataAdapter(sqlStr, sqlConnection);
                System.Data.DataSet ds3 = new System.Data.DataSet();
                dap3.Fill(ds3);

                int rowCnt3 = ds3.Tables[0].Rows.Count;
                if (rowCnt3 == 0)
                {
                    Logger.Error("No SetData records found in ProcessSetData. WorkItemId: {WorkItemId}, SQL: {Sql}", eventData.WorkItemId, sqlStr);
                    return false;
                }
                else
                {
                    SqlCommand cmd2;
                    foreach (DataRow tr in ds3.Tables[0].Rows)
                    {
                        string setDataEventName = tr["EventName"].ToString();
                        string setDataToType = tr["ToType"].ToString();
                        string setDataVariable = tr["Variable"].ToString();
                        string setDataFromType = tr["FromType"].ToString();
                        string setDataValue = tr["Value"].ToString();

                        #region Get the FROM value
                        //*** Get the FROM value *******
                        string fromSetDataValue = "";

                        if (setDataFromType == "Work Item Field")
                        {
                            sqlStr = @"Select fieldValue from ATFieldInstanceString where WorkItemID = @workItemId AND FieldName = @fieldName 
                                       UNION 
                                       Select fieldValue from ATFieldInstanceOption where WorkItemID = @workItemId AND FieldName = @fieldName";
                            fromSetDataValue = Repository.GetRecordValue(sqlConnection, sqlStr, new Dictionary<string, object>{
                                {"@workItemId", eventData.WorkItemId},
                                {"@fieldName", setDataValue}
                            });
                        }

                        if (setDataFromType == "Text")
                        {
                            fromSetDataValue = setDataValue;
                        }

                        if (setDataFromType == "Work Item Attribute")
                        {
                            if (setDataValue == "lastActionUser")
                            {
                                sqlStr = "Select lastAction from ATWorkItemReference where WorkItemID = " + eventData.WorkItemId;
                                fromSetDataValue = Repository.GetRecordValue(sqlConnection, sqlStr);
                                if (fromSetDataValue != "")
                                    fromSetDataValue = fromSetDataValue.Substring(0, fromSetDataValue.IndexOf(":"));
                            }
                            else
                            {
                                if (setDataValue == "creator" || setDataValue == "created" || setDataValue == "Priority" ||
                                    setDataValue == "processId" || setDataValue == "workItemName")
                                {
                                    sqlStr = $"Select {setDataValue} from ATWorkItem where WorkItemID = {eventData.WorkItemId}";
                                    fromSetDataValue = Repository.GetRecordValue(sqlConnection, sqlStr);
                                }
                                else
                                {
                                    sqlStr = $"Select {setDataValue} from ATWorkItemReference where WorkItemID = {eventData.WorkItemId}";
                                    fromSetDataValue = Repository.GetRecordValue(sqlConnection, sqlStr);
                                }
                            }
                        }


                        if (fromSetDataValue == "")
                        {
                            var detailBuilder = new StringBuilder();
                            detailBuilder.AppendLine($"setDataFromType: {setDataFromType}");
                            detailBuilder.AppendLine($"setDataValue: {setDataValue}");

                            Logger.Error("No value retrieved in ProcessSetData for work item {WorkItemId}. Details:\n{Details}", eventData.WorkItemId, detailBuilder.ToString());
                            return false;
                        }

                        #endregion Get the FROM value

                        #region Set the TO value
                        if (fromSetDataValue != "")
                        {

                            if (setDataToType == "Work Item Attribute")
                            {
                                if (setDataVariable == "creator" || setDataVariable == "created" || setDataVariable == "Priority" ||
                                    setDataVariable == "processId" || setDataVariable == "workItemName")
                                {
                                    //TODO: Check ATWorkItem table for FieldName column presence
                                    sqlStr = $"Update ATWorkItem SET {setDataVariable} = N'{fromSetDataValue}' WHERE WorkItemID = {eventData.WorkItemId}";
                                }
                                else
                                {
                                    sqlStr = $"Update ATWorkItemReference SET {setDataVariable} = N'{fromSetDataValue}' WHERE WorkItemID = {eventData.WorkItemId}";
                                }

                                cmd2 = new SqlCommand(sqlStr, sqlConnection);
                                await cmd2.ExecuteNonQueryAsync();
                            }

                            if (setDataToType == "Work Item Field")
                            {
                                sqlStr = @"Update ATFieldInstanceString SET fieldValue = @fieldValue WHERE WorkItemID = @workItemId AND FieldName = @fieldName; 
                                           Update ATFieldInstanceOption SET fieldValue = @fieldValue WHERE WorkItemID = @workItemId AND FieldName = @fieldName";
                                cmd2 = new SqlCommand(sqlStr, sqlConnection);
                                cmd2.Parameters.AddWithValue("@fieldValue", fromSetDataValue);
                                cmd2.Parameters.AddWithValue("@workItemId", eventData.WorkItemId);
                                cmd2.Parameters.AddWithValue("@fieldName", setDataVariable);
                                await cmd2.ExecuteNonQueryAsync();
                            }

                        }

                        #endregion Set the TO value

                    }

                    sqlStr =
                        $@"UPDATE ATWorkItemReference 
                           SET EventID = {eventData.NextEventId}, 
                               PendEventId = 0, 
                               PendQueueId = null, 
                               PendExpirationTime = NULL, 
                               ServerRequest = {(int)ServerRequest.ForwardExistingWorkItem}, 
                               ServerRequestParam = NULL,
                               LastActionDate = '{DateTime.Now}'
                           WHERE WorkItemID = {eventData.WorkItemId}";

                    cmd2 = new SqlCommand(sqlStr, sqlConnection);
                    await cmd2.ExecuteNonQueryAsync();

                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            Logger.Error("An error occurred in ProcessSetData. WorkItemId: {WorkItemId}, Exception: {ExceptionMessage}", eventData.WorkItemId, ex.Message);
            return false;
        }
    }
}