using Ease.NetCore.DataAccess;
using Ease.NetCore.DataAccess.SQL;
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Options;
using System;
using System.Data;
using System.Threading.Tasks;

namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
{
	/// <summary>
	/// 
	/// </summary>
	/// <param name="settings"></param>
	public class ThisSystemService(IOptions<AppSettings> settings) : IThisSystemService
	{
		private readonly AppSettings _settings = settings?.Value;

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public async Task<ThisSystemResponse> GetAsync()
		{
			ThisSystemResponse response = new() { ReturnStatus = 200, CanEditBatch = true };
			try
			{
				using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
				try
				{
					bool canEditBatch = true, canEditPRProcess = true;
					using (IDataReader dr = tc.ExecuteReader("IF EXISTS(SELECT TranID FROM Sales.SalesStockTrans WHERE AuthorisedTime IS NOT NULL AND AuthorisedLoginId IS NOT NULL) SELECT 'D' ELSE SELECT 'E'"))
					{
						if (dr.Read())
						{
							canEditBatch = dr.GetString(0) == "E";
						}
						dr.Close();
					}

					using (IDataReader dr = tc.ExecuteReader("IF EXISTS(SELECT PaymentId FROM Sales.SalesPayments WHERE AuthorizedTime IS NOT NULL AND AuthorizedBy IS NOT NULL) SELECT 'D' ELSE SELECT 'E'"))
					{
						if (dr.Read())
						{
							canEditPRProcess = dr.GetString(0) == "E";
						}
						dr.Close();
					}

					using (IDataReader dr = tc.ExecuteReader("SELECT SystemID, Code, Name, NameInBangla, Address, AddressInBangla, PhoneNo, MobileNo,"
					  + " EmailAddress, WebAddress, VATRegNo, VATRate, PrvntAtckPwdReuse, EnfStgPwd, PwdMinLen, PwdMaxLen, DALastPwds, ExpiryDays,"
					  + " MaxTryCount, LockTime, AppVersion, AutoLogoutParams, PwdRsvdWords, LoginIdCantPwd, BatchEnabled, BmProcessId, PrProcessId"
					  + " FROM ThisSystem"))
					{
						if (dr.Read())
						{
							response = new ThisSystemResponse
							{
								CanEditBatch = canEditBatch,
								CanEditPRProcess = canEditPRProcess,
								ThisSystemId = dr.GetInt32(0),
								Code = dr.GetString(1),
								Name = dr.GetString(2),
								BanglaName = dr.GetString(3),
								Address = dr.GetString(4),
								BanglaAddress = dr.GetString(5),
								PhoneNo = dr.GetString(6),
								MobileNo = dr.GetString(7),
								EmailAddress = dr.GetString(8),
								Website = dr.GetString(9),
								VatRegNo = dr.GetString(10),
								VatRate = dr.GetDecimal(11),
								PreventAttackPasswordReuse = !dr.IsDBNull(12) && dr.GetInt16(12) != 0,
								EnfStgPwd = dr.GetInt16(13) != 0,
								PwdMinLen = dr.GetInt16(14),
								PwdMaxLen = dr.GetInt16(15),
								DisallowLastPwds = dr.GetInt16(16),
								ExpiryDays = dr.GetInt16(17),
								MaxTryCount = dr.GetInt16(18),
								LockTime = dr.GetInt16(19),
								AppVersion = dr.GetString(20),
								AutoLogoutParams = dr.IsDBNull(21) ? "0,0,0" : dr.GetString(21),
								PwdReserveWords = dr.IsDBNull(22) ? string.Empty : dr.GetString(22),
								LoginIdCantBePassword = !dr.IsDBNull(23) && dr.GetInt16(23) != 0,
								BatchEnabled = !dr.IsDBNull(24) && dr.GetInt16(24) != 0,
								BmProcessId = dr.IsDBNull(25) ? 0 : dr.GetInt16(25),
								PrProcessId = dr.IsDBNull(26) ? 0 : dr.GetInt16(26)
							};
						}
						dr.Close();
					}

					tc.End();
				}
				catch (Exception ie)
				{
					tc?.HandleError();

					throw DBCustomError.GenerateCustomError(ie);
				}
			}
			catch (Exception e)
			{
				throw new InvalidOperationException(e.Message, e);
			}

			return response;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		/// <exception cref="Exception"></exception>
		public async Task<WOTermsResponse> GetWOTermsAsync()
		{
			WOTermsResponse response = new() { ReturnStatus = 200 };
			try
			{
				using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
				try
				{
					using IDataReader dr = tc.ExecuteReader("SELECT ItemId, PaymentTerms, TermsAndConditions FROM WOTerms");
					if (dr.Read())
					{
						response = new WOTermsResponse
						{
							ItemId = dr.GetInt32(0),
							PaymentTerms = dr.GetString(1),
							TermsAndConditions = dr.GetString(2)
						};
					}
					dr.Close();

					tc.End();
				}
				catch (Exception ie)
				{
					tc?.HandleError();

					throw DBCustomError.GenerateCustomError(ie);
				}
			}
			catch (Exception e)
			{
				throw new InvalidOperationException(e.Message, e);
			}

			return response;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <param name="ipAddress"></param>
		/// <param name="modifiedBy"></param>
		/// <returns></returns>
		public async Task<bool> SaveAsync(ThisSystemRequest request, string ipAddress, int modifiedBy)
		{
			bool returnValue = false;
			try
			{
				using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
				try
				{
					SqlParameter[] p =
					[
						SqlHelperExtension.CreateInParam(pName: "@Code", pType: SqlDbType.VarChar, pValue: request.Code, size: 15),
						SqlHelperExtension.CreateInParam(pName: "@Name", pType: SqlDbType.VarChar, pValue: request.Name, size: 50),
						SqlHelperExtension.CreateInParam(pName: "@BanglaName", pType: SqlDbType.NVarChar, pValue: request.BanglaName, size: 50),
						SqlHelperExtension.CreateInParam(pName: "@Address", pType: SqlDbType.VarChar, pValue: request.Address, size: 150),
						SqlHelperExtension.CreateInParam(pName: "@BanglaAddress", pType: SqlDbType.NVarChar, pValue: request.BanglaAddress, size: 150),
						SqlHelperExtension.CreateInParam(pName: "@PhoneNo", pType: SqlDbType.VarChar, pValue: request.PhoneNo, size: 50),
						SqlHelperExtension.CreateInParam(pName: "@MobileNo", pType: SqlDbType.VarChar, pValue: request.MobileNo, size: 50),
						SqlHelperExtension.CreateInParam(pName: "@EmailAddress", pType: SqlDbType.VarChar, pValue: request.EmailAddress ?? string.Empty, size: 50),
						SqlHelperExtension.CreateInParam(pName: "@Website", pType: SqlDbType.VarChar, pValue: request.Website, size: 100),
						SqlHelperExtension.CreateInParam(pName: "@VatRegNo", pType: SqlDbType.VarChar, pValue: request.VatRegNo, size: 30),
						SqlHelperExtension.CreateInParam(pName: "@VatRate", pType: SqlDbType.Money, pValue: request.VatRate),
						SqlHelperExtension.CreateInParam(pName: "@EnfStgPwd", pType: SqlDbType.SmallInt, pValue: request.EnfStgPwd ? 1 : 0),
						SqlHelperExtension.CreateInParam(pName: "@PwdMinLen", pType: SqlDbType.SmallInt, pValue: request.PwdMinLen),
						SqlHelperExtension.CreateInParam(pName: "@PwdMaxLen", pType: SqlDbType.SmallInt, pValue: request.PwdMaxLen),
						SqlHelperExtension.CreateInParam(pName: "@DALastPwds", pType: SqlDbType.SmallInt, pValue: request.DisallowLastPwds),
						SqlHelperExtension.CreateInParam(pName: "@ExpiryDays", pType: SqlDbType.SmallInt, pValue: request.ExpiryDays),
						SqlHelperExtension.CreateInParam(pName: "@MaxTryCount", pType: SqlDbType.SmallInt, pValue: request.MaxTryCount),
						SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.SmallInt, pValue: request.LockTime),
						SqlHelperExtension.CreateInParam(pName: "@PrvntAtckPwdReuse", pType: SqlDbType.SmallInt, pValue: request.PreventAttackPasswordReuse?1: 0),
						SqlHelperExtension.CreateInParam(pName: "@AppVersion", pType: SqlDbType.VarChar, pValue: request.AppVersion, size: 11),
						SqlHelperExtension.CreateInParam(pName: "@AutoLogoutParams", pType: SqlDbType.VarChar, pValue: request.AutoLogoutParams, size: 15),
						SqlHelperExtension.CreateInParam(pName: "@PwdReserveWords", pType: SqlDbType.VarChar, pValue: request.PwdReserveWords, size: 150),
						SqlHelperExtension.CreateInParam(pName: "@LoginIdCantPwd", pType: SqlDbType.SmallInt, pValue: request.LoginIdCantBePassword ? 1 : 0),
						SqlHelperExtension.CreateInParam(pName: "@BatchEnabled", pType: SqlDbType.SmallInt, pValue: request.BatchEnabled ? 1 : 0),
						SqlHelperExtension.CreateInParam(pName: "@BmProcessId", pType: SqlDbType.SmallInt, pValue: request.BmProcessId),
						SqlHelperExtension.CreateInParam(pName: "@PrProcessId", pType: SqlDbType.SmallInt, pValue: request.PrProcessId),
						SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
						SqlHelperExtension.CreateInParam(pName: "@ModifiedBy", pType: SqlDbType.Int, pValue: modifiedBy)
					];
					_ = tc.ExecuteNonQuerySp("dbo.UpdateThisSystem", p);

					tc.End();

					returnValue = true;
				}
				catch (Exception ie)
				{
					tc?.HandleError();

					throw DBCustomError.GenerateCustomError(ie);
				}
			}
			catch (Exception e)
			{
				throw new InvalidOperationException(e.Message, e);
			}

			return returnValue;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <param name="ipAddress"></param>
		/// <param name="savedBy"></param>
		/// <returns></returns>
		/// <exception cref="Exception"></exception>
		public async Task<bool> SaveWOTermsAsync(WOTermsRequest request, string ipAddress, int savedBy)
		{
			bool returnValue = false;
			try
			{
				using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
				try
				{
					SqlParameter[] p =
					[
						SqlHelperExtension.CreateInParam(pName: "@PaymentTerms", pType: SqlDbType.NVarChar, pValue: request.PaymentTerms, size: 2000),
						SqlHelperExtension.CreateInParam(pName: "@TermsAndConditions", pType: SqlDbType.NVarChar, pValue: request.TermsAndConditions, size: 2000),
						SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
						SqlHelperExtension.CreateInParam(pName: "@SavedBy", pType: SqlDbType.Int, pValue: savedBy)
					];
					_ = tc.ExecuteNonQuerySp("dbo.SaveWOTerms", p);

					tc.End();

					returnValue = true;
				}
				catch (Exception ie)
				{
					tc?.HandleError();

					throw DBCustomError.GenerateCustomError(ie);
				}
			}
			catch (Exception e)
			{
				throw new InvalidOperationException(e.Message, e);
			}

			return returnValue;
		}
	}
}
