using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.StoredProcedureResults;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Data;

namespace Ladaer.BackEnd.Infrastructures.Services.Report.Orders
{
    /// <summary>
    /// Giao diện cho dịch vụ báo cáo tài chính đơn hàng
    /// </summary>
    public interface IOrderFinReportService
    {
        /// <summary>
        /// Lấy thống kê chuyển khoản ngân hàng theo sale
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng hiện tại</param>
        /// <returns>Danh sách thống kê chuyển khoản theo sale</returns>
        Task<List<BankTransferSummaryBySaleResult>> GetBankTransferSummaryBySaleAsync(
            SmartTableParam param,
            int userId);
    }

    /// <summary>
    /// Dịch vụ báo cáo tài chính đơn hàng
    /// </summary>
    public class OrderFinReportService : IOrderFinReportService
    {
        private readonly IDbConnection _dbConnection;
        private readonly IUserService _userService;

        /// <summary>
        /// Khởi tạo một thể hiện của <see cref="OrderFinReportService"/>.
        /// </summary>
        /// <param name="dbConnection">Kết nối cơ sở dữ liệu.</param>
        /// <param name="userService">Dịch vụ quản lý người dùng.</param>
        public OrderFinReportService(IDbConnection dbConnection, IUserService userService)
        {
            _dbConnection = dbConnection;
            _userService = userService;
        }

        /// <summary>
        /// Lấy thống kê chuyển khoản ngân hàng theo sale
        /// </summary>
        /// <param name="param">Tham số bảng thông minh</param>
        /// <param name="userId">ID người dùng hiện tại</param>
        /// <returns>Danh sách thống kê chuyển khoản theo sale</returns>
        public Task<List<BankTransferSummaryBySaleResult>> GetBankTransferSummaryBySaleAsync(
            SmartTableParam param,
            int userId)
        {
            return Task.FromResult(GetBankTransferSummaryBySale(param, userId));
        }

        /// <summary>
        /// Lấy thống kê chuyển khoản ngân hàng theo sale (synchronous)
        /// </summary>
        private List<BankTransferSummaryBySaleResult> GetBankTransferSummaryBySale(
            SmartTableParam param,
            int userId)
        {
            var results = new List<BankTransferSummaryBySaleResult>();

            try
            {
                // Xử lý tham số từ SmartTableParam
                DateTimeOffset? startDate = null;
                DateTimeOffset? endDate = null;
                int? customerId = null;
                int? saleId = null;
                string? statusListCsv = null;
                string? physicalStatusListCsv = null;

                // Kiểm tra quyền của user hiện tại
                var userRoles = _userService.GetRolesAsync(userId).Result;
                var isFounder = userRoles.Any(r => r.ToLower().Equals("founder", StringComparison.OrdinalIgnoreCase)
                || r.ToLower().Equals("accountant", StringComparison.OrdinalIgnoreCase));

                // Nếu không phải Founder, chỉ được xem dữ liệu của chính mình
                if (!isFounder && userId > 0)
                {
                    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
                        startDate = start.ToLocalTime().StartOfDay();
                        endDate = end.ToLocalTime().EndOfDay();
                    }

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

                    // Chỉ Founder mới có thể lọc theo SaleId
                    if (isFounder && search.SaleId != null)
                    {
                        saleId = (int)search.SaleId;
                    }

                    // Lọc theo nhiều trạng thái (ưu tiên danh sách nếu có)
                    try
                    {
                        if (search.Statuses != null)
                        {
                            var list = new List<int>();
                            foreach (var x in search.Statuses)
                            {
                                if (x == null) continue;
                                list.Add(Convert.ToInt32(x));
                            }
                            if (list.Count > 0)
                            {
                                statusListCsv = string.Join(",", list);
                            }
                        }
                        else if (search.Statuses != null)
                        {
                            statusListCsv = Convert.ToInt32(search.Status).ToString();
                        }

                        if (search.PhysicalStatuses != null)
                        {
                            var list = new List<int>();
                            foreach (var x in search.PhysicalStatuses)
                            {
                                if (x == null) continue;
                                list.Add(Convert.ToInt32(x));
                            }
                            if (list.Count > 0)
                            {
                                physicalStatusListCsv = string.Join(",", list);
                            }
                        }
                        else if (search.PhysicalStatus != null)
                        {
                            physicalStatusListCsv = Convert.ToInt32(search.PhysicalStatus).ToString();
                        }
                    }
                    catch { }
                }

                using var command = _dbConnection.CreateCommand();
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = "sp_GetBankTransferSummaryBySale";

                // Thêm parameters
                command.Parameters.Add(new SqlParameter("@StartDate", startDate ?? (object)DBNull.Value));
                command.Parameters.Add(new SqlParameter("@EndDate", endDate ?? (object)DBNull.Value));
                command.Parameters.Add(new SqlParameter("@CustomerId", customerId ?? (object)DBNull.Value));
                command.Parameters.Add(new SqlParameter("@SaleId", saleId ?? (object)DBNull.Value));
                command.Parameters.Add(new SqlParameter("@StatusList", (object?)statusListCsv ?? DBNull.Value));
                command.Parameters.Add(new SqlParameter("@PhysicalStatusList", (object?)physicalStatusListCsv ?? DBNull.Value));

                if (_dbConnection.State != ConnectionState.Open)
                {
                    _dbConnection.Open();
                }

                using var reader = command.ExecuteReader();

                while (reader.Read())
                {
                    var result = new BankTransferSummaryBySaleResult
                    {
                        SaleId = reader.GetInt32(reader.GetOrdinal("SaleId")),
                        SaleName = reader.GetString(reader.GetOrdinal("SaleName")),
                        SalePhoneNumber = reader.GetString(reader.GetOrdinal("SalePhoneNumber")),
                        TotalOrders = reader.GetInt32(reader.GetOrdinal("TotalOrders")),
                        SumTotalFee = reader.GetDecimal(reader.GetOrdinal("SumTotalFee")),
                        TotalTransferFee = reader.GetDecimal(reader.GetOrdinal("TotalTransferFee")),
                        NotCollectAmount = reader.GetDecimal(reader.GetOrdinal("NotCollectAmount")),
                        NotCollectedCount = reader.GetInt32(reader.GetOrdinal("NotCollectedCount")),
                        CreatedBillAmount = reader.GetDecimal(reader.GetOrdinal("CreatedBillAmount")),
                        CountCreatedBill = reader.GetInt32(reader.GetOrdinal("CountCreatedBill")),
                        TotalCollected = reader.GetDecimal(reader.GetOrdinal("TotalCollected")),
                        CountCollected = reader.GetInt32(reader.GetOrdinal("CountCollected"))
                    };

                    results.Add(result);
                }
            }
            catch (Exception ex)
            {
                // Log error if needed
                throw new Exception($"Lỗi khi thực thi stored procedure sp_GetBankTransferSummaryBySale: {ex.Message}", ex);
            }

            return results;
        }
    }
}
