using System.Data;
using System.Diagnostics;
using IWS5.Core.Enums;
using IWS5.Core.Models.Processing;
using Microsoft.Data.SqlClient;
using ILogger = Serilog.ILogger;

namespace IWS5.Server.EventProcessors;

public class CodeProcessor(ILogger logger, IConfiguration configuration) : EventProcessor(logger, configuration)
{
    public override async Task<bool> ProcessEventAsync(EventModel eventData, int processId)
    {
        await using (var sqlConnection = new SqlConnection(ConnectionString))
        {
            var sqlStr = $"SELECT TOP (1) codeName, codePath, codeArgs FROM ATCode With (NoWait) where processId = {eventData.CurrentProcessId} AND EventId = {eventData.CurrentEventId}";
            SqlDataAdapter dap2 = new SqlDataAdapter(sqlStr, sqlConnection);
            DataSet ds2 = new DataSet();
            dap2.Fill(ds2);

            var codePath = ds2.Tables[0].Rows[0][1].ToString();
            var codeArgs = ds2.Tables[0].Rows[0][2].ToString() ?? "";

            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = codePath,
                    Arguments = codeArgs,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };
            process.Start();

            string stdout = "";
            string stderr = "";
            while (!process.StandardOutput.EndOfStream || !process.StandardError.EndOfStream)
            {
                if (!process.StandardOutput.EndOfStream)
                {
                    var line = process.StandardOutput.ReadLine();
                    if (line != null)
                    {
                        stdout += line + "\n";
                    }
                }

                if (!process.StandardError.EndOfStream)
                {
                    var line = process.StandardError.ReadLine();
                    if (line != null)
                    {
                        stderr += line + "\n";
                    }
                }
            }

            await process.WaitForExitAsync();
            int newServerRequestVal = process.ExitCode == 0 ? (int)ServerRequest.ForwardExistingWorkItem : (int)ServerRequest.ErrorWorkItem;

            sqlStr = $"UPDATE ATWorkItemReference SET EventID = {eventData.NextEventId}, ServerRequest = {newServerRequestVal}, ServerRequestParam = NULL, LastActionDate = '{DateTime.Now}' WHERE WorkItemID = {eventData.WorkItemId}";
            SqlCommand cmd2 = new SqlCommand(sqlStr, sqlConnection);
            await cmd2.ExecuteNonQueryAsync();

            if (process.ExitCode != 0)
            {
                logger.Error("WorkItem {WorkItemId} did not return successful exit code for Code task. Exit code: {ExitCode}\nSTDOUT: {StdOut}\nSTDERR: {StdErr}", eventData.WorkItemId, process.ExitCode, stdout, stderr);
            }

            return true;
        }
    }
}