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.MobileApp;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.MobileApp;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.MobileApp;

public class MobileMasterDataService : IMobileMasterDataService
{
    private readonly AppSettings _settings;
    private readonly IUserService _userService;
    private readonly IIntegrationHttpService _httpService;

    public MobileMasterDataService(IOptions<AppSettings> options, IUserService userService, IIntegrationHttpService httpService)
    {
        _settings = options.Value;
        _userService = userService;
        _httpService = httpService;
    }

    public async Task<MarketHeirarchyByEmpResponse> GetMarketHeirarchiesByEmpAsync(GetMarketHeirarchyByEmpRequest request)
    {

        MarketHeirarchyByEmpResponse response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                string employeeNumber = request.EmployeeNumber;

                response.Companies = await GetCompaniesByEmployeeNumberAsync(tc, employeeNumber);
                response.SalesOrgs = await GetSalesOrgsByEmployeeNumberAsync(tc, employeeNumber);
                response.DistributionChannels = await GetDistributionChannelsByEmployeeNumberAsync(tc, employeeNumber);
                response.Regions = await GetRegionsByEmployeeNumberAsync(tc, employeeNumber);
                response.Areas = await GetAreasByEmployeeNumberAsync(tc, employeeNumber);
                response.Teritories = await GetTerritoriesByEmployeeNumberAsync(tc, employeeNumber);
                response.Plants = await GetPlantsByEmployeeNumberAsync(tc, employeeNumber);

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

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

        return response;
    }

    public async Task<PagedResult<GetBrandResponse>> GetBrandsAsync(GetBrandsRequest request)
    {
        PagedResult<GetBrandResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@BrandCode", pType: SqlDbType.VarChar, pValue: request.BrandCode),
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrganization", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetBrandsPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetBrandResponse
                        {
                            BrandCode = dr.GetString(0),
                            BrandName = dr.GetString(1)
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }


    public async Task<PagedResult<GetMaterialResponse>> GetMaterialsAsync(GetMaterialsRequest request)
    {
        PagedResult<GetMaterialResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@BrandCode", pType: SqlDbType.VarChar, pValue: request.BrandCode),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetMaterialsPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetMaterialResponse
                        {
                            MaterialCode = dr.GetString(0),
                            MaterialName = dr.GetString(1),
                            TypeCode = dr.GetString(2),
                            TypeName = dr.GetString(3),
                            GroupCode = dr.GetString(4),
                            GroupName = dr.GetString(5),
                            BaseUnitMeasurement = dr.GetString(6),
                            SalesUnitMeasurement = dr.GetString(7),
                            UnitConversionValue = dr.GetDecimal(8),
                            BrandCode = dr.GetString(9),
                            BrandName = dr.GetString(10),
                            SalesOrg = dr.GetString(11)
                        });

                    }
                    dr.Close();


                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;

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

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

        return response;
    }

    public async Task<PagedResult<GetMaterialStockReponse>> GetMaterialsStockAsync(GetMaterialStockRequest request)
    {
        PagedResult<GetMaterialStockReponse> response = new();
        try
        {
            //var httpStockResponse = await _httpService.GetMaterialStockAsync(request.PlantCode);

            //response.Items = httpStockResponse.Select(p => new GetMaterialStockReponse
            //{
            //    MaterialCode = p.MaterialCode,
            //    PlantCode = p.PlantCode,
            //    AvailableStock = p.AvailableStock,
            //}).ToList();

            var materialResponse = await GetMaterialsAsync(new GetMaterialsRequest());

            foreach (var item in materialResponse.Items)
            {
                response.Items.Add(
                    new GetMaterialStockReponse() { PlantCode = request.PlantCode, MaterialCode = item.MaterialCode, AvailableStock = Random.Shared.Next(5, 500) });
            }
        }
        catch (Exception)
        {
            throw;
        }

        return response;
    }

    public async Task<PagedResult<GetMaterialPriceResponse>> GetMaterialPricesAsync(GetMaterialPriceRequest request)
    {
        PagedResult<GetMaterialPriceResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@BrandCode", pType: SqlDbType.VarChar, pValue: request.BrandCode),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetMaterialPricePaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetMaterialPriceResponse
                        {
                            SalesOrgCode = dr.GetString(0),
                            CustomerCode = dr.GetString(1),
                            MaterialCode = dr.GetString(2),
                            BasePrice = dr.GetDecimal(3)
                        });
                    }
                    dr.Close();


                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;

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

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

        return response;
    }

    public async Task<PagedResult<GetCustomerResponse>> GetCustomersAsync(GetCustomersRequest request)
    {
        string companyCode = string.Empty;
        PagedResult<GetCustomerResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@TeritoryCode", pType: SqlDbType.VarChar, pValue: request.TeritoryCode),
                     SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetCustomersPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetCustomerResponse
                        {
                            CustomerCode = dr.GetString(0),
                            CustomerName = dr.GetString(1),
                            AccountGroupCode = dr.GetString(2),
                            AccountGroupDescription = dr.GetString(3),
                            DistributionChannelCode = dr.GetString(4),
                            DistributionChannelName = dr.GetString(5),
                            DivisionCode = dr.GetString(6),
                            DivisionName = dr.GetString(7),
                            MobileNumber = dr.GetString(8),
                            EmailAddress = dr.GetString(9),
                            TaxNumber = dr.GetString(10),
                            SalesGroupCode = dr.GetString(11),
                            SalesGroupName = dr.GetString(12),
                            CustomerGroupCode = dr.GetString(13),
                            CustomerGroupName = dr.GetString(14),
                            CustomerPriceGroupCode = dr.GetString(15),
                            CustomerPriceGroupName = dr.GetString(16),
                            PaymentTermCode = dr.GetString(17),
                            TeritoryCode = dr.GetString(18),
                            SalesOrgCode = dr.GetString(19),
                            PlantCode = dr.GetString(20),
                            IsCreditCustomer  = dr.GetInt32(21) > 0 ,
                            CreditLimit = dr.GetDecimal(22),
                            CreditBalance = dr.GetDecimal(23),
                            CreditOverdue = dr.GetDecimal(24),
                        });
                        companyCode = dr.GetString(25);
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();


                if (!string.IsNullOrWhiteSpace(request.CustomerCode))
                {
                    var customerLedger = await _httpService.GetCustomerLedgerAsync(request.CustomerCode, companyCode);
                    if(customerLedger != null)
                    {
                        response.Items = response.Items.Select(x =>
                        {
                            x.CreditBalance = customerLedger.CurrentBalance;
                            x.CreditOverdue = customerLedger.OverdueAmount;
                            return x;
                        }).ToList();
                    }             
                }
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }

    private async Task<List<EmpCompanyResponse>> GetCompaniesByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<EmpCompanyResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetCompaniesByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new EmpCompanyResponse
                    {
                        CompanyCode = dr.GetString(0),
                        CompanyName = dr.GetString(1)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<SalesOrgResponse>> GetSalesOrgsByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<SalesOrgResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetSalesOrgsByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new SalesOrgResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        SalesOrgName = dr.GetString(2)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<DistibutionChannleResponse>> GetDistributionChannelsByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<DistibutionChannleResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetDistributionChannelsByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new DistibutionChannleResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        DistributorChannelCode = dr.GetString(2),
                        DistributorChannelName = dr.GetString(3)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<RegionResponse>> GetRegionsByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<RegionResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetRegionsByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new RegionResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        RegionCode = dr.GetString(2),
                        RegionName = dr.GetString(3)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<AreaResponse>> GetAreasByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<AreaResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetAreasByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new AreaResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        RegionCode = dr.GetString(2),
                        AreaCode = dr.GetString(3),
                        AreaName = dr.GetString(4)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<TeritoryResponse>> GetTerritoriesByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<TeritoryResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetTerritoriesByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new TeritoryResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        RegionCode = dr.GetString(2),
                        AreaCode = dr.GetString(3),
                        TeritoryCode = dr.GetString(4),
                        TeritoryName = dr.GetString(5)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    private async Task<List<PlantResponse>> GetPlantsByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
    {
        List<PlantResponse> response = [];

        try
        {
            SqlParameter[] p =
            [
                SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
            ];

            using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetPlantsByEmployeeNumber", parameterValues: p))
            {
                while (dr.Read())
                {
                    response.Add(new PlantResponse
                    {
                        CompanyCode = dr.GetString(0),
                        SalesOrgCode = dr.GetString(1),
                        PlantCode = dr.GetString(2),
                        PlantName = dr.GetString(3)
                    });
                }
                dr.Close();
            }
        }
        catch (Exception ex)
        {
            throw DBCustomError.GenerateCustomError(ex);
        }

        return response;
    }

    public async Task<GetAttendanceByEmpResponse> GetAttendanceByEmpAsync(GetAttendanceByEmpRequest request)
    {
        GetAttendanceByEmpResponse response = new();

        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                    SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                    SqlHelperExtension.CreateInParam(pName: "@AttendanceDate", pType: SqlDbType.Date, pValue: request.AttendanceDate)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetAttendanceByEmployee", parameterValues: p))
                {
                    if (dr.Read())
                    {
                        response = MapToResponse(dr);
                    }
                    dr.Close();
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();
                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }

    public async Task<GetAttendanceByEmpResponse> UpsertAttendanceByEmpAsync(UpsertAttendanceByEmpRequest request)
    {
        GetAttendanceByEmpResponse response = new();

        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode,true);
            try
            {
                SqlParameter[] p =
                [
                    SqlHelperExtension.CreateInParam(pName: "@AttendanceDate", pType: SqlDbType.Date, pValue: DateTime.Now),
                    SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                    SqlHelperExtension.CreateInParam(pName: "@CheckInTime", pType: SqlDbType.DateTime, pValue: request.CheckInTime != null ? DateTime.Today.Add(request.CheckInTime.Value) : null),
                    SqlHelperExtension.CreateInParam(pName: "@CheckInLatitude", pType: SqlDbType.VarChar, pValue: request.CheckInLatitude),
                    SqlHelperExtension.CreateInParam(pName: "@CheckInLongitude", pType: SqlDbType.VarChar, pValue: request.CheckInLongitude),
                    SqlHelperExtension.CreateInParam(pName: "@CheckInLocationName", pType: SqlDbType.VarChar, pValue: request.CheckInLocationName),
                    SqlHelperExtension.CreateInParam(pName: "@CheckOutTime", pType: SqlDbType.DateTime,  pValue: request.CheckOutTime != null ? DateTime.Today.Add(request.CheckOutTime.Value) : null),
                    SqlHelperExtension.CreateInParam(pName: "@CheckOutLatitude", pType: SqlDbType.VarChar, pValue: request.CheckOutLatitude),
                    SqlHelperExtension.CreateInParam(pName: "@CheckOutLongitude", pType: SqlDbType.VarChar, pValue: request.CheckOutLongitude),
                    SqlHelperExtension.CreateInParam(pName: "@CheckOutLocationName", pType: SqlDbType.VarChar, pValue: request.CheckOutLocationName)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.UpsertAttendanceByEmployee", parameterValues: p))
                {
                    if (dr.Read())
                    {
                        response = MapToResponse(dr);
                    }
                    dr.Close();
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();
                throw DBCustomError.GenerateCustomError(ie);
            }
        }
        catch (Exception ex)
        {
            throw;
        }

        return response;
    }

    private static GetAttendanceByEmpResponse MapToResponse(IDataReader dr)
    {
        return new GetAttendanceByEmpResponse
        {
            AttendanceDate = dr.GetDateTime(0),
            EmployeeNumber = dr.GetString(1),
            CheckInTime = dr.IsDBNull(2) ? null : dr.GetDateTime(2).TimeOfDay,
            CheckInLatitude = dr.IsDBNull(3) ? null : dr.GetString(3),
            CheckInLongitude = dr.IsDBNull(4) ? null : dr.GetString(4),
            CheckInLocationName = dr.IsDBNull(5) ? null : dr.GetString(5),
            CheckOutTime = dr.IsDBNull(6) ? null : dr.GetDateTime(6).TimeOfDay,
            CheckOutLatitude = dr.IsDBNull(7) ? null : dr.GetString(7),
            CheckOutLongitude = dr.IsDBNull(8) ? null : dr.GetString(8),
            CheckOutLocationName = dr.IsDBNull(9) ? null : dr.GetString(9)
        };
    }

    public async Task<PagedResult<GetDiscountResponse>> GetDiscountAsync(GetDiscountRequest request)
    {
        PagedResult<GetDiscountResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode),                
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@DiscountCode", pType: SqlDbType.VarChar, pValue: request.DiscountCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetDiscountPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetDiscountResponse
                        {
                            SalesOrgcCode = dr.GetString(0),
                            DiscountCode = dr.GetString(1),
                            DiscountName = dr.GetString(2),
                            DistributorChannelCode = dr.GetString(3),
                            DistributorChannelName = dr.GetString(4),
                            CalculationType = dr.GetString(5)
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }

    public async Task<PagedResult<GetDiscountMaterialResponse>> GetDiscountMaterialsAsync(GetDiscountMaterialRequest request)
    {
        PagedResult<GetDiscountMaterialResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@DiscountCode", pType: SqlDbType.VarChar, pValue: request.DiscountCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetDiscountMaterialsPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetDiscountMaterialResponse
                        {
                            DiscountCode = dr.GetString(0),
                            CustomerCode = dr.GetString(1),
                            MaterialCode = dr.GetString(2),
                            UnitOfMeasurement = dr.GetString(3),
                            CalculationType = dr.GetString(4),
                            DiscountValue = dr.GetDecimal(5),
                            StartDate = dr.GetDateTime(6),
                            EndDate = dr.GetDateTime(7),
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }


    public async Task<PagedResult<GetFOCResponse>> GetFOCsAsync(GetFOCRequest request)
    {
        PagedResult<GetFOCResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@DiscountCode", pType: SqlDbType.VarChar, pValue: request.FOCCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetFOCPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetFOCResponse
                        {
                            SalesOrgcCode = dr.GetString(0),
                            FOCCode = dr.GetString(1),
                            FOCName = dr.GetString(2),
                            DistributorChannelCode = dr.GetString(3),
                            DistributorChannelName = dr.GetString(4)
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }

    public async Task<PagedResult<GetFOCMaterialResponse>> GetFOCMaterialsAsync(GetFOCMaterialRequest request)
    {
        PagedResult<GetFOCMaterialResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode),
                     SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: request.EmployeeNumber),
                     SqlHelperExtension.CreateInParam(pName: "@MaterialCode", pType: SqlDbType.VarChar, pValue: request.MaterialCode),
                     SqlHelperExtension.CreateInParam(pName: "@DiscountCode", pType: SqlDbType.VarChar, pValue: request.FOCCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetFOCMaterialsPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetFOCMaterialResponse
                        {
                            FOCCode = dr.GetString(0),
                            CustomerCode = dr.GetString(1),
                            MaterialCode = dr.GetString(2),
                            UnitOfMeasurement = dr.GetString(3),
                            MinimumOrderQty = dr.GetDecimal(4),
                            ForQuantity = dr.GetDecimal(5),
                            FreeQty = dr.GetDecimal(6),
                            FOCUnitOfMeasurement = dr.GetString(7),
                            StartDate = dr.GetDateTime(8),
                            EndDate = dr.GetDateTime(9),
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }

    public async Task<PagedResult<GetPaymentTermResponse>> GetPaymentTermsAsync(GetPaymentTermRequest request)
    {
        PagedResult<GetPaymentTermResponse> response = new();
        try
        {
            using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
            try
            {
                SqlParameter[] p =
                [
                     SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode),
                     SqlHelperExtension.CreateInParam(pName: "@PaymentTermCode", pType: SqlDbType.VarChar, pValue: request.PaymentTermCode),
                     SqlHelperExtension.CreateInParam(pName: "@PageNumber", pType: SqlDbType.Int, pValue: request.PageNumber),
                     SqlHelperExtension.CreateInParam(pName: "@PageSize", pType: SqlDbType.Int, pValue: request.PageSize)
                ];

                using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetPaymentTermsPaginated", parameterValues: p))
                {
                    while (dr.Read())
                    {
                        response.Items.Add(new GetPaymentTermResponse
                        {
                           PaymentTermId = dr.GetInt32(0),
                           PaymentTermCode = dr.GetString(1),
                           PaymentTermDescription = dr.GetString(2),
                           SalesOrgCode = dr.GetString(3),
                           StartDate = dr.GetDateTime(4),
                           EndDate = dr.GetDateTime(5),
                           PaymentTermType = dr.GetString(6),
                        });
                    }
                    dr.Close();

                    response.TotalCount = response.Items.Count;
                    response.PageNumber = request.PageNumber;
                    response.PageSize = request.PageSize;
                }
                tc.End();
            }
            catch (Exception ie)
            {
                tc?.HandleError();

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

        return response;
    }
}

