using System.Data;
using Dapper;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Reports.Items.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Reports.Results;
using Ladaer.BackEnd.Infrastructures.Services.Identity;

namespace Ladaer.BackEnd.Infrastructures.Services.Report.SaleReports
{
    /// <summary>
    /// Interface dịch vụ báo cáo bán hàng
    /// </summary>
    public interface ISaleReportService
    {
        /// <summary>
        /// Lấy thống kê doanh thu theo sale từ stored procedure
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Kết quả thống kê doanh thu</returns>
        Task<SaleRevenueResult> GetSaleRevenueStatisticsAsync(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy thống kê đơn hàng và doanh thu theo ngày từ stored procedure
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Danh sách thống kê đơn hàng và doanh thu theo ngày</returns>
        Task<OrderRevenueResult> GetOrderRevenueStatisticsByDateAsync(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy thống kê doanh thu theo ngày nhận tiền từ stored procedure
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Danh sách thống kê doanh thu theo ngày nhận tiền</returns>
        Task<OrderRevenueByCollectionDateResult> GetOrderRevenueByCollectionDateAsync(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy thống kê doanh thu theo Sale (chỉ thống kê tài chính) từ stored procedure
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Danh sách thống kê theo Sale</returns>
        Task<OrderRevenueBySaleResult> GetOrderRevenueBySaleAsync(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy thống kê doanh thu theo khách hàng từ stored procedure
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Kết quả thống kê doanh thu theo khách hàng</returns>
        Task<CustomerRevenueResult> GetCustomerRevenueStatisticsAsync(SmartTableParam param, int userId);

        /// <summary>
        /// Lấy thông tin quyền của user cho báo cáo doanh thu theo khách hàng
        /// </summary>
        /// <param name="userId">ID người dùng</param>
        /// <returns>Thông tin quyền</returns>
        Task<CustomerRevenuePermissionsResult> GetCustomerRevenuePermissionsAsync(int userId);
    }

    /// <summary>
    /// Dịch vụ báo cáo bán hàng
    /// </summary>
    public class SaleReportService : ISaleReportService
    {
        private readonly IDbConnection _dbConnection;
        private readonly IUserService _userService;

        public SaleReportService(IDbConnection dbConnection, IUserService userService)
        {
            _dbConnection = dbConnection;
            _userService = userService;
        }

        /// <inheritdoc />
        public async Task<SaleRevenueResult> GetSaleRevenueStatisticsAsync(SmartTableParam param, int userId)
        {
            var result = new SaleRevenueResult();
            const string storeName = "sp_GetSaleRevenueStatistics";

            try
            {
                var currentUser = await _userService.GetByIdAsync(userId);
                if (currentUser == null)
                {
                    result.Message = "Không tìm thấy thông tin người dùng";
                    return result;
                }

                var userRoles = await _userService.GetRolesAsync(userId);
                var isFounder = userRoles.Any(r => r.Equals("Founder", StringComparison.OrdinalIgnoreCase));

                DateTimeOffset? fromDate = null;
                DateTimeOffset? toDate = null;
                int? saleId = null;
                string? saleIds = null;

                if (!isFounder)
                {
                    saleId = userId;
                }

                if (param?.Search?.PredicateObject != null)
                {
                    dynamic search = param.Search.PredicateObject;

                    if (search.StartDate != null && search.EndDate != null)
                    {
                        DateTimeOffset start = search.StartDate;
                        DateTimeOffset end = search.EndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        fromDate = start.ToLocalTime().StartOfDay();
                        toDate = end.ToLocalTime().EndOfDay();
                    }

                    if (isFounder)
                    {
                        if (search.SaleId != null)
                        {
                            saleId = (int)search.SaleId;
                        }
                        else if (search.SaleIds != null)
                        {
                            var saleIdList = new List<int>();

                            if (search.SaleIds is Newtonsoft.Json.Linq.JArray jArray)
                            {
                                foreach (var item in jArray)
                                {
                                    if (int.TryParse(item.ToString(), out int id))
                                    {
                                        saleIdList.Add(id);
                                    }
                                }
                            }
                            else if (search.SaleIds is System.Collections.IEnumerable enumerable)
                            {
                                foreach (var item in enumerable)
                                {
                                    if (int.TryParse(item.ToString(), out int id))
                                    {
                                        saleIdList.Add(id);
                                    }
                                }
                            }

                            if (saleIdList.Count > 0)
                            {
                                saleIds = string.Join(",", saleIdList);
                            }
                        }
                    }
                }

                var parameters = new DynamicParameters();
                parameters.Add("StartDate", fromDate);
                parameters.Add("EndDate", toDate);
                parameters.Add("SaleId", saleId);
                parameters.Add("SaleIds", saleIds);

                result.Items = [.. await _dbConnection.QueryAsync<SaleRevenueItem>(
                    storeName,
                    parameters,
                    commandType: CommandType.StoredProcedure)];

                result.TotalRecord = result.Items.Count;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <inheritdoc />
        public async Task<OrderRevenueResult> GetOrderRevenueStatisticsByDateAsync(SmartTableParam param, int userId)
        {
            var result = new OrderRevenueResult();
            const string storeName = "sp_GetOrderRevenueStatisticsByDate";

            try
            {
                // Xử lý tham số từ SmartTableParam
                DateTimeOffset? fromDate = null;
                DateTimeOffset? toDate = null;

                DateTimeOffset? pickupStartDate = null;
                DateTimeOffset? pickupEndDate = null;

                DateTimeOffset? deliveryStartDate = null;
                DateTimeOffset? deliveryEndDate = null;

                var saleId = (int?)null;

                if (userId <= 0)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Không xác định được người dùng";
                    return result;
                }

                var roles = await _userService.GetRolesAsync(userId);

                if (!roles.Any(r => r == "Founder"))
                {
                    saleId = userId;
                }

                if (param?.Search?.PredicateObject != null)
                {
                    dynamic search = param.Search.PredicateObject;

                    if (search.StartDate != null && search.EndDate != null)
                    {
                        DateTimeOffset start = search.StartDate;
                        DateTimeOffset end = search.EndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        fromDate = start.ToLocalTime().StartOfDay();
                        toDate = end.ToLocalTime().EndOfDay();
                    }

                    // Xử lý PickupStartDate và PickupEndDate
                    if (search.PickupStartDate != null && search.PickupEndDate != null)
                    {
                        DateTimeOffset pickupStart = search.PickupStartDate;
                        DateTimeOffset pickupEnd = search.PickupEndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        pickupStartDate = pickupStart.ToLocalTime().StartOfDay();
                        pickupEndDate = pickupEnd.ToLocalTime().EndOfDay();
                    }

                    // Xử lý DeliveryStartDate và DeliveryEndDate (ngày giao thành công)
                    if (search.DeliveryStartDate != null && search.DeliveryEndDate != null)
                    {
                        DateTimeOffset deliveryStart = search.DeliveryStartDate;
                        DateTimeOffset deliveryEnd = search.DeliveryEndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        deliveryStartDate = deliveryStart.ToLocalTime().StartOfDay();
                        deliveryEndDate = deliveryEnd.ToLocalTime().EndOfDay();
                    }

                    // Xử lý SaleId
                    if (search.SaleId != null && !saleId.HasValue)
                    {
                        saleId = (int)search.SaleId;
                    }
                }

                // Validation: Yêu cầu phải có ít nhất một bộ lọc ngày
                bool hasCreatedDateFilter = fromDate.HasValue && toDate.HasValue;
                bool hasPickupDateFilter = pickupStartDate.HasValue && pickupEndDate.HasValue;
                bool hasDeliveryDateFilter = deliveryStartDate.HasValue && deliveryEndDate.HasValue;

                if (!hasCreatedDateFilter && !hasPickupDateFilter && !hasDeliveryDateFilter)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Vui lòng chọn ít nhất một bộ lọc: Ngày tạo đơn, Ngày lấy hàng hoặc Ngày giao thành công";
                    return result;
                }

                var parameters = new DynamicParameters();
                parameters.Add("StartDate", fromDate);
                parameters.Add("EndDate", toDate);
                parameters.Add("SaleId", saleId);
                parameters.Add("PickupStartDate", pickupStartDate);
                parameters.Add("PickupEndDate", pickupEndDate);
                parameters.Add("DeliveryStartDate", deliveryStartDate);
                parameters.Add("DeliveryEndDate", deliveryEndDate);

                // Gọi stored procedure và map trực tiếp sang OrderRevenueItem
                result.Items = [.. await _dbConnection.QueryAsync<OrderRevenueItem>(
                    storeName,
                    parameters,
                    commandType: CommandType.StoredProcedure)];

                result.TotalRecord = result.Items.Count;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <inheritdoc />
        public async Task<OrderRevenueByCollectionDateResult> GetOrderRevenueByCollectionDateAsync(SmartTableParam param, int userId)
        {
            var result = new OrderRevenueByCollectionDateResult();
            const string storeName = "sp_GetOrderRevenueStatisticsByCollectionDate_Optimized";

            try
            {
                // Xử lý tham số từ SmartTableParam
                DateTimeOffset fromDate = DateTimeOffset.Now.AddDays(-30).StartOfDay(); // Mặc định 30 ngày gần nhất
                DateTimeOffset toDate = DateTime.Now.EndOfDay();

                var saleId = (int?)null;

                if (userId <= 0)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Không xác định được người dùng";
                    return result;
                }

                var roles = await _userService.GetRolesAsync(userId);

                if (!roles.Any(r => r.ToLower().Equals("founder", StringComparison.OrdinalIgnoreCase) ||
                r.ToLower().Equals("accountant", StringComparison.OrdinalIgnoreCase)))
                {
                    saleId = userId;
                }

                if (param?.Search?.PredicateObject != null)
                {
                    dynamic search = param.Search.PredicateObject;

                    if (search.StartDate != null && search.EndDate != null)
                    {
                        DateTimeOffset start = search.StartDate;
                        DateTimeOffset end = search.EndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        fromDate = start.ToLocalTime().DateTime.StartOfDay();
                        toDate = end.ToLocalTime().DateTime.EndOfDay();
                    }

                    // Xử lý SaleId
                    if (search.SaleId != null && !saleId.HasValue)
                    {
                        saleId = (int)search.SaleId;
                    }
                }

                var parameters = new DynamicParameters();
                parameters.Add("StartDate", fromDate);
                parameters.Add("EndDate", toDate);
                parameters.Add("SaleId", saleId);

                // Gọi stored procedure và map trực tiếp sang OrderRevenueByCollectionDateItem
                result.Items = [.. await _dbConnection.QueryAsync<OrderRevenueByCollectionDateItem>(
                    storeName,
                    parameters,
                    commandType: CommandType.StoredProcedure)];

                result.TotalRecord = result.Items.Count;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <inheritdoc />
        public async Task<OrderRevenueBySaleResult> GetOrderRevenueBySaleAsync(SmartTableParam param, int userId)
        {
            var result = new OrderRevenueBySaleResult();
            const string storeName = "sp_GetOrderRevenueStatisticsBySale_Optimized";

            try
            {
                // Xử lý tham số từ SmartTableParam
                DateTimeOffset fromDate = DateTimeOffset.Now.AddDays(-30).StartOfDay(); // Mặc định 30 ngày gần nhất
                DateTimeOffset toDate = DateTime.Now.EndOfDay();

                var saleId = (int?)null;

                if (userId <= 0)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Không xác định được người dùng";
                    return result;
                }

                var roles = await _userService.GetRolesAsync(userId);

                // Founder và Accountant được xem tất cả; còn lại chỉ xem của mình
                if (!roles.Any(r => r.ToLower().Equals("founder", StringComparison.OrdinalIgnoreCase) ||
                    r.ToLower().Equals("accountant", StringComparison.OrdinalIgnoreCase)))
                {
                    saleId = userId;
                }

                if (param?.Search?.PredicateObject != null)
                {
                    dynamic search = param.Search.PredicateObject;

                    if (search.StartDate != null && search.EndDate != null)
                    {
                        DateTimeOffset start = search.StartDate;
                        DateTimeOffset end = search.EndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        fromDate = start.ToLocalTime().StartOfDay();
                        toDate = end.ToLocalTime().EndOfDay();
                    }

                    // Xử lý SaleId
                    if (search.SaleId != null && !saleId.HasValue)
                    {
                        saleId = (int)search.SaleId;
                    }
                }

                var parameters = new DynamicParameters();
                parameters.Add("StartDate", fromDate);
                parameters.Add("EndDate", toDate);
                parameters.Add("SaleId", saleId);

                result.Items = [.. await _dbConnection.QueryAsync<OrderRevenueBySaleItem>(
                    storeName,
                    parameters,
                    commandType: CommandType.StoredProcedure)];

                result.TotalRecord = result.Items.Count;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <inheritdoc />
        public async Task<CustomerRevenueResult> GetCustomerRevenueStatisticsAsync(SmartTableParam param, int userId)
        {
            var result = new CustomerRevenueResult();
            const string storeName = "sp_GetSaleRevenueByCustomer";

            try
            {
                // Xử lý tham số từ SmartTableParam
                DateTimeOffset? fromDate = null;
                DateTimeOffset? toDate = null;

                var customerId = (int?)null;
                var customerIds = (string?)null;
                var saleId = (int?)null;

                if (userId <= 0)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Không xác định được người dùng";
                    return result;
                }

                var roles = await _userService.GetRolesAsync(userId);

                // Founder và Accountant được xem tất cả; còn lại chỉ xem của mình
                if (!roles.Any(r => r.ToLower().Equals("founder", StringComparison.OrdinalIgnoreCase) ||
                    r.ToLower().Equals("accountant", StringComparison.OrdinalIgnoreCase)))
                {
                    saleId = userId;
                }

                if (param?.Search?.PredicateObject != null)
                {
                    dynamic search = param.Search.PredicateObject;

                    if (search.StartDate != null && search.EndDate != null)
                    {
                        DateTimeOffset start = search.StartDate;
                        DateTimeOffset end = search.EndDate;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        fromDate = start.ToLocalTime().StartOfDay();
                        toDate = end.ToLocalTime().EndOfDay();
                    }

                    // Xử lý CustomerId
                    if (search.CustomerId != null)
                    {
                        customerId = (int)search.CustomerId;
                    }

                    // Xử lý CustomerIds (chỉ cho Founder/Accountant)
                    if (search.CustomerIds != null && !saleId.HasValue)
                    {
                        var customerIdList = new List<int>();

                        if (search.CustomerIds is Newtonsoft.Json.Linq.JArray jArray)
                        {
                            foreach (var item in jArray)
                            {
                                if (int.TryParse(item.ToString(), out int id))
                                {
                                    customerIdList.Add(id);
                                }
                            }
                        }
                        else if (search.CustomerIds is System.Collections.IEnumerable enumerable)
                        {
                            foreach (var item in enumerable)
                            {
                                if (int.TryParse(item.ToString(), out int id))
                                {
                                    customerIdList.Add(id);
                                }
                            }
                        }

                        if (customerIdList.Count > 0)
                        {
                            customerIds = string.Join(",", customerIdList);
                        }
                    }

                    // Xử lý SaleId (chỉ cho Founder/Accountant)
                    if (search.SaleId != null && !saleId.HasValue)
                    {
                        saleId = (int)search.SaleId;
                    }
                }

                // Lấy thông tin phân trang từ SmartTableParam
                int pageNumber = param.Pagination?.PageIndex ?? 1;
                int pageSize = param.Pagination?.PageSize ?? 25;

                var parameters = new DynamicParameters();
                parameters.Add("StartDate", fromDate);
                parameters.Add("EndDate", toDate);
                parameters.Add("CustomerId", customerId);
                parameters.Add("CustomerIds", customerIds);
                parameters.Add("SaleId", saleId);
                parameters.Add("PageNumber", pageNumber);
                parameters.Add("PageSize", pageSize);

                result.Items = [.. await _dbConnection.QueryAsync<CustomerRevenueItem>(
                    storeName,
                    parameters,
                    commandType: CommandType.StoredProcedure)];

                // Lấy TotalRecords từ kết quả đầu tiên
                var resultList = result.Items.ToList();
                result.TotalRecord = resultList.FirstOrDefault()?.TotalRecords ?? 0;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <inheritdoc />
        public async Task<CustomerRevenuePermissionsResult> GetCustomerRevenuePermissionsAsync(int userId)
        {
            var result = new CustomerRevenuePermissionsResult();

            try
            {
                if (userId <= 0)
                {
                    result.Result = Lada.Framework.DTO.Result.Failed;
                    result.Message = "Không xác định được người dùng";
                    return result;
                }

                var roles = await _userService.GetRolesAsync(userId);

                // Founder và Accountant được chọn sale và nhiều khách hàng
                var isFounder = roles.Any(r => r.Equals("Founder", StringComparison.OrdinalIgnoreCase));
                var isAccountant = roles.Any(r => r.Equals("Accountant", StringComparison.OrdinalIgnoreCase));

                result.CanSelectSale = isFounder || isAccountant;
                result.CanSelectMultipleCustomers = isFounder || isAccountant;
            }
            catch (Exception ex)
            {
                result.Result = Lada.Framework.DTO.Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }
    }
}

