using DocumentFormat.OpenXml.Wordprocessing;
using Ease.NetCore.DataAccess;
using Ease.NetCore.DataAccess.SQL;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Options;
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using System;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;

public class IntegrationService : IIntegrationService
{
    private readonly AppSettings _settings;

    public IntegrationService(IOptions<AppSettings> options)
    {
        _settings = options.Value;
    }

    public async Task<CustomerByCompanyCodeResponse> GetCustomerByCompanyCodeAsync(CustomerByCompanyCodeRequest request)
    {
        CustomerByCompanyCodeResponse response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                await GetCustomerByCompanyCodeAsync(tc, request);
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }


    public async Task<CustomerIntegrationResponse> UpsertCustomerAsync(CustomerIntegrationRequest request)
    {
        CustomerIntegrationResponse response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode,true);
            try
            {
                var customer = await GetCustomerByCompanyCodeAsync(tc, new CustomerByCompanyCodeRequest() { CompanyCode = request.CompanyCode, CustomerNumber = request.CustomerNumber });

                if( customer != null && customer.CustomerId>0)
                {
                    //Update Here
                    UpdateCustomer(tc, customer.CustomerId, request);
                    response.CustomerNumber = request.CustomerNumber;
                    response.CompanyCode = request.CompanyCode;
                    response.IsUpdated = true;

                }
                else
                {
                    //Insert Here 

                    CreateCustomer(tc, request);
                    response.CustomerNumber = request.CustomerNumber;
                    response.CompanyCode = request.CompanyCode;
                    response.IsUpdated = false;

                }

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

                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }

    private async Task<CustomerByCompanyCodeResponse> GetCustomerByCompanyCodeAsync(TransactionContext tc, CustomerByCompanyCodeRequest request)
    {
        CustomerByCompanyCodeResponse response = new CustomerByCompanyCodeResponse();
        try
        {
            SqlParameter[] p =
            [
               SqlHelperExtension.CreateInParam(pName: "@CustomerNumber", pType: SqlDbType.NVarChar,pValue: request.CustomerNumber ),
               SqlHelperExtension.CreateInParam(pName: "@CompanyCode", pType: SqlDbType.NVarChar,pValue: request.CompanyCode ),

            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetCustomerByCompanyCode", parameterValues: p))
            {
                if (dr.Read())
                {
                    response = new CustomerByCompanyCodeResponse()
                    {
                        CustomerId =Convert.ToInt32( dr["CustomerId"].ToString()),
                        CustomerNumber = dr["CustomerNumber"].ToString(),
                        CustomerName = dr["CustomerName"].ToString(),
                        AccountGroup = dr["AccountGroup"].ToString(),
                        AccountGroupDescription = dr["AccountGroupDescription"].ToString(),
                        CompanyCode = dr["CompanyCode"].ToString(),
                        CompanyCodeDescription = dr["CompanyCodeDescription"].ToString(),
                        SalesOrganization = dr["SalesOrganization"].ToString(),
                        SalesOrganizationDescription = dr["SalesOrganizationDescription"].ToString(),
                        DistributionChannel = dr["DistributionChannel"].ToString(),
                        DistributionChannelDescription = dr["DistributionChannelDescription"].ToString(),
                        Division = dr["Division"].ToString(),
                        DivisionDescription = dr["DivisionDescription"].ToString(),
                        MobileNumber = dr["MobileNumber"].ToString(),
                        EmailAddress = dr["EmailAddress"].ToString(),
                        BusinessTaxNumber = dr["BusinessTaxNumber"].ToString(),
                        CreditLimit = dr["CreditLimit"] == DBNull.Value ? 0 : Convert.ToDecimal(dr["CreditLimit"]),
                        SalesOffice = dr["SalesOffice"].ToString(),
                        SalesOfficeDescription = dr["SalesOfficeDescription"].ToString(),
                        SalesGroup = dr["SalesGroup"].ToString(),
                        CustomerGroup = dr["CustomerGroup"].ToString(),
                        Status = dr["Status"].ToString(),
                        PaymentTerms = dr["PaymentTerms"].ToString(),
                        SearchTerm = dr["SearchTerm"].ToString(),
                        Region = dr["Region"].ToString(),
                        RegionName = dr["RegionName"].ToString(),
                        Area = dr["Area"].ToString(),
                        AreaName = dr["AreaName"].ToString(),
                        SalesUnit = dr["SalesUnit"].ToString(),
                        SalesUnitName = dr["SalesUnitName"].ToString(),
                        Territory = dr["Territory"].ToString(),
                        TerritoryName = dr["TerritoryName"].ToString(),
                        Plant = dr["Plant"].ToString(),
                        PlantName = dr["PlantName"].ToString()

                    };
                }
                dr.Close();
            }
        }
        catch(Exception ex)
        {
            throw;
        }
        return response;
    }


    public async Task<EmployeeIntegrationResponse> GetEmployeeBySalesOrgAsync(EmployeeBySalesOrgCodeRequest request)
    {
        EmployeeIntegrationResponse response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                await GetEmployeeBySalesOrgAsync(tc, request);
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }

    public async Task<bool> UpsertEmployeeAsync(EmployeeIntegrationRequest request)
    {
        bool response = false;
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                EmployeeIntegrationResponse employee = await GetEmployeeBySalesOrgAsync(tc, new EmployeeBySalesOrgCodeRequest() { SalesOrgCode = request.SalesOrgCode, EmployeeVendorCode = request.EmployeeVendorCode });
                SqlParameter[] p =
                [
                    SqlHelperExtension.CreateInParam(pName: "@EmployeeVendorCode", pType: SqlDbType.NVarChar, pValue: request.EmployeeVendorCode),
                    SqlHelperExtension.CreateInParam(pName: "@EmployeeVendorName", pType: SqlDbType.NVarChar, pValue: request.EmployeeVendorName),
                    SqlHelperExtension.CreateInParam(pName: "@DesignationCode", pType: SqlDbType.NVarChar, pValue: request.DesignationCode),
                    SqlHelperExtension.CreateInParam(pName: "@DesignationDescription", pType: SqlDbType.NVarChar, pValue: request.DesignationDescription),
                    SqlHelperExtension.CreateInParam(pName: "@MobileNo", pType: SqlDbType.NVarChar, pValue: request.MobileNo),
                    SqlHelperExtension.CreateInParam(pName: "@Email", pType: SqlDbType.NVarChar, pValue: request.Email),
                    SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.NVarChar, pValue: request.SalesOrgCode),
                    SqlHelperExtension.CreateInParam(pName: "@SalesOrgDescription", pType: SqlDbType.NVarChar, pValue: request.SalesOrgDescription),
                    SqlHelperExtension.CreateInParam(pName: "@DistChannelCode", pType: SqlDbType.NVarChar, pValue: request.DistChannelCode),
                    SqlHelperExtension.CreateInParam(pName: "@DistChannelDescription", pType: SqlDbType.NVarChar, pValue: request.DistChannelDescription),
                    SqlHelperExtension.CreateInParam(pName: "@DivisionCode", pType: SqlDbType.NVarChar, pValue: request.DivisionCode),
                    SqlHelperExtension.CreateInParam(pName: "@DivisionDescription", pType: SqlDbType.NVarChar, pValue: request.DivisionDescription),
                    SqlHelperExtension.CreateInParam(pName: "@RegionAAl", pType: SqlDbType.NVarChar, pValue: request.RegionAAl),
                    SqlHelperExtension.CreateInParam(pName: "@AreaCode", pType: SqlDbType.NVarChar, pValue: request.AreaCode),
                    SqlHelperExtension.CreateInParam(pName: "@AreaDescription", pType: SqlDbType.NVarChar, pValue: request.AreaDescription),
                    SqlHelperExtension.CreateInParam(pName: "@SalesUnitACCLCode", pType: SqlDbType.NVarChar, pValue: request.SalesUnitACCLCode),
                    SqlHelperExtension.CreateInParam(pName: "@SalesUnitACCLDescription", pType: SqlDbType.NVarChar, pValue: request.SalesUnitACCLDescription),
                    SqlHelperExtension.CreateInParam(pName: "@TerritoryCode", pType: SqlDbType.NVarChar, pValue: request.TerritoryCode),
                    SqlHelperExtension.CreateInParam(pName: "@TerritoryDescription", pType: SqlDbType.NVarChar, pValue: request.TerritoryDescription),
                    SqlHelperExtension.CreateInParam(pName: "@SalesOfficeCode", pType: SqlDbType.NVarChar, pValue: request.SalesOfficeCode),
                    SqlHelperExtension.CreateInParam(pName: "@SalesOfficeDescription", pType: SqlDbType.NVarChar, pValue: request.SalesOfficeDescription),
                    SqlHelperExtension.CreateInParam(pName: "@PlantCode", pType: SqlDbType.NVarChar, pValue: request.PlantCode),
                    SqlHelperExtension.CreateInParam(pName: "@PlantDescription", pType: SqlDbType.NVarChar, pValue: request.PlantDescription),
                    SqlHelperExtension.CreateInParam(pName: "@Status", pType: SqlDbType.NVarChar, pValue: request.Status),
                    SqlHelperExtension.CreateInParam(pName: "@StatusDescription", pType: SqlDbType.NVarChar, pValue: request.StatusDescription),

                ];

                if (employee != null && employee.EmployeeVendorId > 0)
                {
                    _= tc.ExecuteNonQuerySp("dbo.UpdateEmployee", p);
                }
                else
                {
                    _= tc.ExecuteNonQuerySp("dbo.InsertEmployee", p);
                }

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

                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }

    private async Task<EmployeeIntegrationResponse> GetEmployeeBySalesOrgAsync(TransactionContext tc, EmployeeBySalesOrgCodeRequest request)
    {
        EmployeeIntegrationResponse response = new EmployeeIntegrationResponse();
        try
        {
            SqlParameter[] p =
            [
               SqlHelperExtension.CreateInParam(pName: "@EmployeeVendorCode", pType: SqlDbType.NVarChar,pValue: request.EmployeeVendorCode ),
               SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.NVarChar,pValue: request.SalesOrgCode ),

            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetEmployeeBySalesOrgCode", parameterValues: p))
            {
                if (dr.Read())
                {
                    response = new EmployeeIntegrationResponse()
                    {
                        EmployeeVendorId = dr.GetInt32(0),
                        EmployeeVendorCode = dr.GetString(1),
                        EmployeeVendorName = dr.GetString(2),
                        DesignationCode = dr.GetString(3),
                        DesignationDescription = dr.GetString(4),
                        MobileNo = dr.GetString(5),
                        Email = dr.GetString(6),
                        SalesOrgCode = dr.GetString(7),
                        SalesOrgDescription = dr.GetString(8),
                        DistChannelCode = dr.GetString(9),
                        DistChannelDescription = dr.GetString(10),
                        DivisionCode = dr.GetString(11),
                        DivisionDescription = dr.GetString(12),
                        RegionAAl = dr.GetString(13),
                        AreaCode = dr.GetString(14),
                        AreaDescription = dr.GetString(15),
                        SalesUnitACCLCode = dr.GetString(16),
                        SalesUnitACCLDescription = dr.GetString(17),
                        TerritoryCode = dr.GetString(18),
                        TerritoryDescription = dr.GetString(19),
                        SalesOfficeCode = dr.GetString(20),
                        SalesOfficeDescription = dr.GetString(21),
                        PlantCode = dr.GetString(22),
                        PlantDescription = dr.GetString(23),
                        Status = dr.GetString(24),
                        StatusDescription = dr.GetString(25)
                        
                    };
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }
        return response;
    }

    public bool CreateCustomer(TransactionContext tc, CustomerIntegrationRequest request)
    {
        bool returnValue = false;

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam("@CustomerNumber", SqlDbType.VarChar, request.CustomerNumber),
                SqlHelperExtension.CreateInParam("@CustomerName", SqlDbType.VarChar, request.CustomerName),

                SqlHelperExtension.CreateInParam("@AccountGroup", SqlDbType.VarChar, request.AccountGroup),
                SqlHelperExtension.CreateInParam("@AccountGroupDescription", SqlDbType.VarChar, request.AccountGroupDescription),

                SqlHelperExtension.CreateInParam("@CompanyCode", SqlDbType.VarChar, request.CompanyCode),
                SqlHelperExtension.CreateInParam("@CompanyCodeDescription", SqlDbType.VarChar, request.CompanyCodeDescription),

                SqlHelperExtension.CreateInParam("@SalesOrganization", SqlDbType.VarChar, request.SalesOrganization),
                SqlHelperExtension.CreateInParam("@SalesOrganizationDescription", SqlDbType.VarChar, request.SalesOrganizationDescription),

                SqlHelperExtension.CreateInParam("@DistributionChannel", SqlDbType.VarChar, request.DistributionChannel),
                SqlHelperExtension.CreateInParam("@DistributionChannelDescription", SqlDbType.VarChar, request.DistributionChannelDescription),

                SqlHelperExtension.CreateInParam("@Division", SqlDbType.VarChar, request.Division),
                SqlHelperExtension.CreateInParam("@DivisionDescription", SqlDbType.VarChar, request.DivisionDescription),

                SqlHelperExtension.CreateInParam("@MobileNumber", SqlDbType.VarChar, request.MobileNumber),
                SqlHelperExtension.CreateInParam("@EmailAddress", SqlDbType.VarChar, request.EmailAddress),

                SqlHelperExtension.CreateInParam("@BusinessTaxNumber", SqlDbType.VarChar, request.BusinessTaxNumber),
                SqlHelperExtension.CreateInParam("@CreditLimit", SqlDbType.Decimal, request.CreditLimit),

                SqlHelperExtension.CreateInParam("@SalesOffice", SqlDbType.VarChar, request.SalesOffice),
                SqlHelperExtension.CreateInParam("@SalesOfficeDescription", SqlDbType.VarChar, request.SalesOfficeDescription),

                SqlHelperExtension.CreateInParam("@SalesGroup", SqlDbType.VarChar, request.SalesGroup),
                SqlHelperExtension.CreateInParam("@CustomerGroup", SqlDbType.VarChar, request.CustomerGroup),

                SqlHelperExtension.CreateInParam("@Status", SqlDbType.VarChar, request.Status),
                SqlHelperExtension.CreateInParam("@PaymentTerms", SqlDbType.VarChar, request.PaymentTerms),

                SqlHelperExtension.CreateInParam("@SearchTerm", SqlDbType.VarChar, request.SearchTerm),

                SqlHelperExtension.CreateInParam("@Region", SqlDbType.VarChar, request.Region),
                SqlHelperExtension.CreateInParam("@RegionName", SqlDbType.VarChar, request.RegionName),

                SqlHelperExtension.CreateInParam("@Area", SqlDbType.VarChar, request.Area),
                SqlHelperExtension.CreateInParam("@AreaName", SqlDbType.VarChar, request.AreaName),

                SqlHelperExtension.CreateInParam("@SalesUnit", SqlDbType.VarChar, request.SalesUnit),
                SqlHelperExtension.CreateInParam("@SalesUnitName", SqlDbType.VarChar, request.SalesUnitName),

                SqlHelperExtension.CreateInParam("@Territory", SqlDbType.VarChar, request.Territory),
                SqlHelperExtension.CreateInParam("@TerritoryName", SqlDbType.VarChar, request.TerritoryName),

                SqlHelperExtension.CreateInParam("@Plant", SqlDbType.VarChar, request.Plant),
                SqlHelperExtension.CreateInParam("@PlantName", SqlDbType.VarChar, request.PlantName)
            ];

            _ = tc.ExecuteNonQuerySp(spName: "dbo.CreateCustomer", parameterValues: p);

            returnValue = true;
        }
        catch (Exception e)
        {
            throw;
        }

        return returnValue;
    }

    public bool UpdateCustomer(TransactionContext tc,int customerId, CustomerIntegrationRequest request)
    {
        bool returnValue = false;

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam("@CustomerId", SqlDbType.Int,customerId),
                SqlHelperExtension.CreateInParam("@CustomerNumber", SqlDbType.VarChar, request.CustomerNumber),
                SqlHelperExtension.CreateInParam("@CompanyCode", SqlDbType.VarChar, request.CompanyCode),

                SqlHelperExtension.CreateInParam("@CustomerName", SqlDbType.VarChar, request.CustomerName),
                SqlHelperExtension.CreateInParam("@AccountGroup", SqlDbType.VarChar, request.AccountGroup),
                SqlHelperExtension.CreateInParam("@AccountGroupDescription", SqlDbType.VarChar, request.AccountGroupDescription),

                SqlHelperExtension.CreateInParam("@CompanyCodeDescription", SqlDbType.VarChar, request.CompanyCodeDescription),

                SqlHelperExtension.CreateInParam("@SalesOrganization", SqlDbType.VarChar, request.SalesOrganization),
                SqlHelperExtension.CreateInParam("@SalesOrganizationDescription", SqlDbType.VarChar, request.SalesOrganizationDescription),

                SqlHelperExtension.CreateInParam("@DistributionChannel", SqlDbType.VarChar, request.DistributionChannel),
                SqlHelperExtension.CreateInParam("@DistributionChannelDescription", SqlDbType.VarChar, request.DistributionChannelDescription),

                SqlHelperExtension.CreateInParam("@Division", SqlDbType.VarChar, request.Division),
                SqlHelperExtension.CreateInParam("@DivisionDescription", SqlDbType.VarChar, request.DivisionDescription),

                SqlHelperExtension.CreateInParam("@MobileNumber", SqlDbType.VarChar, request.MobileNumber),
                SqlHelperExtension.CreateInParam("@EmailAddress", SqlDbType.VarChar, request.EmailAddress),

                SqlHelperExtension.CreateInParam("@BusinessTaxNumber", SqlDbType.VarChar, request.BusinessTaxNumber),
                SqlHelperExtension.CreateInParam("@CreditLimit", SqlDbType.Decimal, request.CreditLimit),

                SqlHelperExtension.CreateInParam("@SalesOffice", SqlDbType.VarChar, request.SalesOffice),
                SqlHelperExtension.CreateInParam("@SalesOfficeDescription", SqlDbType.VarChar, request.SalesOfficeDescription),

                SqlHelperExtension.CreateInParam("@SalesGroup", SqlDbType.VarChar, request.SalesGroup),
                SqlHelperExtension.CreateInParam("@CustomerGroup", SqlDbType.VarChar, request.CustomerGroup),

                SqlHelperExtension.CreateInParam("@Status", SqlDbType.VarChar, request.Status),
                SqlHelperExtension.CreateInParam("@PaymentTerms", SqlDbType.VarChar, request.PaymentTerms),

                SqlHelperExtension.CreateInParam("@SearchTerm", SqlDbType.VarChar, request.SearchTerm),

                SqlHelperExtension.CreateInParam("@Region", SqlDbType.VarChar, request.Region),
                SqlHelperExtension.CreateInParam("@RegionName", SqlDbType.VarChar, request.RegionName),

                SqlHelperExtension.CreateInParam("@Area", SqlDbType.VarChar, request.Area),
                SqlHelperExtension.CreateInParam("@AreaName", SqlDbType.VarChar, request.AreaName),

                SqlHelperExtension.CreateInParam("@SalesUnit", SqlDbType.VarChar, request.SalesUnit),
                SqlHelperExtension.CreateInParam("@SalesUnitName", SqlDbType.VarChar, request.SalesUnitName),

                SqlHelperExtension.CreateInParam("@Territory", SqlDbType.VarChar, request.Territory),
                SqlHelperExtension.CreateInParam("@TerritoryName", SqlDbType.VarChar, request.TerritoryName),

                SqlHelperExtension.CreateInParam("@Plant", SqlDbType.VarChar, request.Plant),
                SqlHelperExtension.CreateInParam("@PlantName", SqlDbType.VarChar, request.PlantName)
            ];

            _ = tc.ExecuteNonQuerySp(
                spName: "dbo.UpdateCustomerById",
                parameterValues: p
            );

            returnValue = true;
        }
        catch (Exception e)
        {
            throw new InvalidOperationException(e.Message, e);
        }

        return returnValue;
    }


}
