using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Domains.Finance;
using Lada.Framework.Data.Domains.Finance.Wallets;
using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.Data.Enums;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Finances;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Finances;
using Ladaer.BackEnd.Infrastructures.DTO.Profiles;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Finances;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Microsoft.EntityFrameworkCore;
using ExpenseStatus = Lada.Framework.Data.Enums.ExpenseStatus;

namespace Ladaer.BackEnd.Infrastructures.Services.Finances
{
    /// <summary>
    /// Interface cho service quản lý chi phí
    /// </summary>
    public interface IExpenseService
    {
        /// <summary>
        /// Tìm kiếm chi phí
        /// </summary>
        /// <param name="param">Tham số tìm kiếm</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả tìm kiếm</returns>
        Task<SmartTableResult<ExpenseItem>> Search(SmartTableParam param, CurrentUser currentUser);

        /// <summary>
        /// Lấy thông tin chi tiết của chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Thông tin chi tiết chi phí</returns>
        Task<ExpenseItem?> GetById(Guid id, CurrentUser currentUser);

        /// <summary>
        /// Tạo mới hoặc cập nhật chi phí
        /// </summary>
        /// <param name="model">Thông tin chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả tạo hoặc cập nhật</returns>
        Task<BaseResult> CreateOrUpdate(ExpenseModel model, CurrentUser currentUser);

        /// <summary>
        /// Duyệt chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả duyệt</returns>
        Task<BaseResult> Approve(Guid id, CurrentUser currentUser);

        /// <summary>
        /// Bỏ duyệt chi phí (chuyển về trạng thái chờ duyệt)
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả bỏ duyệt</returns>
        Task<BaseResult> Unapprove(Guid id, CurrentUser currentUser);

        /// <summary>
        /// Từ chối chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="rejectReason">Lý do từ chối</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả từ chối</returns>
        Task<BaseResult> Reject(Guid id, string rejectReason, CurrentUser currentUser);

        /// <summary>
        /// Đánh dấu chi phí đã chuyển tiền
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <param name="note">Ghi chú</param>
        /// <returns>Kết quả đánh dấu chuyển tiền</returns>
        Task<BaseResult> MarkAsPaid(Guid id, CurrentUser currentUser, string note = "");

        /// <summary>
        /// Xóa chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả xóa</returns>
        Task<BaseResult> Delete(Guid id, CurrentUser currentUser);
    }

    /// <summary>
    /// Service quản lý chi phí
    /// </summary>
    public class ExpenseService : IExpenseService
    {
        private readonly IRepository<Expense> _expenseRepository;
        private readonly IRepository<ExpenseCategory> _expenseCategoryRepository;
        private readonly IRepository<ExpenseHistory> _expenseHistoryRepository;
        private readonly IUserRepository<User> _userRepository;
        private readonly IRepository<Wallet> _walletRepository;
        private readonly IRepository<Transaction> _transactionRepository;
        private readonly IRepository<UserBankAccount> _userBankAccountRepository;
        private readonly IPermissionService _permissionService;

        /// <summary>
        /// Khởi tạo một thể hiện của <see cref="ExpenseService"/>.
        /// </summary>
        /// <param name="expenseRepository">Đối tượng IRepository của Expense.</param>
        /// <param name="expenseCategoryRepository">Đối tượng IRepository của ExpenseCategory.</param>
        /// <param name="userRepository">Đối tượng IUserRepository của User.</param>
        /// <param name="walletRepository">Đối tượng IRepository của Wallet.</param>
        /// <param name="transactionRepository">Đối tượng IRepository của Transaction.</param>
        /// <param name="userBankAccountRepository">Đối tượng IRepository của UserBankAccount.</param>
        /// <param name="permissionService">Service quản lý quyền.</param>
        public ExpenseService(
            IRepository<Expense> expenseRepository, 
            IRepository<ExpenseCategory> expenseCategoryRepository,
            IRepository<ExpenseHistory> expenseHistoryRepository,
            IUserRepository<User> userRepository, 
            IRepository<Wallet> walletRepository, 
            IRepository<Transaction> transactionRepository, 
            IRepository<UserBankAccount> userBankAccountRepository, 
            IPermissionService permissionService)
        {
            _expenseRepository = expenseRepository;
            _expenseCategoryRepository = expenseCategoryRepository;
            _expenseHistoryRepository = expenseHistoryRepository;
            _userRepository = userRepository;
            _walletRepository = walletRepository;
            _transactionRepository = transactionRepository;
            _userBankAccountRepository = userBankAccountRepository;
            _permissionService = permissionService;
        }

        /// <summary>
        /// Tìm kiếm chi phí
        /// </summary>
        /// <param name="param">Tham số tìm kiếm</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả tìm kiếm</returns>
        public async Task<SmartTableResult<ExpenseItem>> Search(SmartTableParam param, CurrentUser currentUser)
        {
            IQueryable<Expense> query = _expenseRepository.Query()
                .Include(e => e.ExpenseCategory);

            // Kiểm tra quyền xem chi phí
            query = await ApplyViewPermissionsFilter(query, currentUser);

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

                if (search.Keyword != null)
                {
                    string keyword = search.Keyword;
                    keyword = keyword.Trim().ToLower();
                    query = query.Where(x => x.Description.ToLower().Contains(keyword) || x.Note.ToLower().Contains(keyword));
                }

                if (search.ExpenseCategoryId != null && search.ExpenseCategoryId > 0)
                {
                    int categoryId = search.ExpenseCategoryId;
                    query = query.Where(x => x.ExpenseCategoryId == categoryId);
                }

                if (search.Status != null)
                {
                    ExpenseStatus status = search.Status;
                    query = query.Where(x => x.Status == status);
                }

                if (search.CreatedStart != null && search.CreatedEnd != null)
                {
                    DateTimeOffset start = search.CreatedStart;
                    DateTimeOffset end = search.CreatedEnd;
                    // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                    DateTimeOffset startParam = start.ToLocalTime().StartOfDay();
                    DateTimeOffset endParam = end.ToLocalTime().EndOfDay();
                    query = query.Where(x => x.CreatedTime >= startParam && x.CreatedTime <= endParam);
                }
            }

            param.Sort = new Sort() { Predicate = "CreatedTime", Reverse = true };

            // Include ExpenseCategory để lấy tên danh mục
            var result = await query.Include(e => e.ExpenseCategory)
                .ToSmartTableResultAsync(param, x => FinanceMappingExtensions.ToItem(x));

            // Lấy thông tin ApprovedByUserName
            if (result.Items.Any())
            {
                var approvedByIds = result.Items.Where(x => x.ApprovedBy.HasValue && x.ApprovedBy > 0)
                    .Select(x => x.ApprovedBy!.Value).Distinct().ToList();
                if (approvedByIds.Any())
                {
                    var users = await _userRepository.Query()
                        .Where(u => approvedByIds.Contains(u.Id))
                        .Select(u => new { u.Id, u.UserName })
                        .ToListAsync();

                    foreach (var item in result.Items)
                    {
                        if (item.ApprovedBy.HasValue && item.ApprovedBy > 0)
                        {
                            var user = users.FirstOrDefault(u => u.Id == item.ApprovedBy.Value);
                            item.ApprovedByUserName = user?.UserName ?? "";
                        }
                    }
                }

                // Tính toán permissions cho từng item
                var expenseIds = result.Items.Select(x => x.Id).ToList();
                var expenses = await _expenseRepository.Query()
                    .Include(e => e.ExpenseCategory)
                    .Where(e => expenseIds.Contains(e.Id))
                    .ToListAsync();

                foreach (var item in result.Items)
                {
                    var expense = expenses.FirstOrDefault(e => e.Id == item.Id);
                    if (expense != null)
                    {
                        await CalculatePermissions(item, expense, currentUser);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Lấy thông tin chi tiết của chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Thông tin chi tiết chi phí</returns>
        public async Task<ExpenseItem?> GetById(Guid id, CurrentUser currentUser)
        {
            if (id == Guid.Empty)
            {
                return null;
            }

            var expense = await _expenseRepository.Query()
                .Include(e => e.ExpenseCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expense == null)
            {
                return null;
            }

            // Kiểm tra quyền xem chi phí
            if (!await HasViewPermission(expense, currentUser))
            {
                return null; // Không có quyền xem, trả về null
            }

            var expenseItem = FinanceMappingExtensions.ToItem(expense);

            // Tính toán permissions
            await CalculatePermissions(expenseItem, expense, currentUser);

            //Người phê duyệt
            if (expenseItem.Id != Guid.Empty && expenseItem.ApprovedBy > 0)
            {
                var approver = await _userRepository.Query().FirstOrDefaultAsync(u => u.Id == expenseItem.ApprovedBy);
                if (approver != null && approver.Id > 0)
                {
                    expenseItem.ApprovedByUserName = approver != null && approver.UserName != null ?
                                                        approver.UserName : string.Empty;
                }
            }

            // Lấy danh sách lịch sử thay đổi trạng thái
            var histories = await _expenseHistoryRepository.Query()
                .Where(h => h.ExpenseId == id)
                .OrderByDescending(h => h.CreatedTime)
                .ToListAsync();

            if (histories.Any())
            {
                expenseItem.Histories = histories.Select(h => h.ToItem()).ToList();
            }

            return expenseItem;
        }

        /// <summary>
        /// Tạo mới hoặc cập nhật chi phí
        /// </summary>
        /// <param name="model">Thông tin chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> CreateOrUpdate(ExpenseModel model, CurrentUser currentUser)
        {
            var result = new BaseResult { Result = Result.Success };

            try
            {
                // Lấy thông tin ExpenseCategory để lấy ApprovedBy mặc định
                var expenseCategory = await _expenseCategoryRepository.Query()
                    .FirstOrDefaultAsync(c => c.Id == model.ExpenseCategoryId);

                if (expenseCategory == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy danh mục chi phí yêu cầu!";
                    return result;
                }

                if (model.Id != Guid.Empty)
                {
                    // Cập nhật - chỉ cập nhật thông tin cơ bản, không thay đổi Status và RejectReason
                    var existingExpense = await _expenseRepository.Query()
                        .FirstOrDefaultAsync(e => e.Id == model.Id);

                    if (existingExpense == null)
                    {
                        result.Result = Result.Failed;
                        result.Message = "Không tìm thấy chi phí cần cập nhật!";
                        return result;
                    }

                    // Cập nhật trực tiếp trên entity hiện có để tránh tracking conflict
                    existingExpense.Description = model.Description;
                    existingExpense.Note = model.Note;
                    existingExpense.Amount = model.Amount;
                    existingExpense.ExpenseCategoryId = model.ExpenseCategoryId;
                    existingExpense.ApprovedBy = expenseCategory.ApprovedBy;
                    existingExpense.UserBankAccountId = model.UserBankAccountId;
                    existingExpense.UpdatedTime = DateTimeHelper.CurrentTime();
                    existingExpense.UpdatedBy = currentUser.UserId;
                    existingExpense.UpdatedByUserName = currentUser.UserName;

                    // Copy thông tin ngân hàng nếu có UserBankAccountId
                    await CopyBankAccountInfo(existingExpense, model.UserBankAccountId);

                    await _expenseRepository.UpdateAsync(existingExpense);

                    // Ghi lịch sử cập nhật (không thay đổi status)
                    var updateNote = $"Cập nhật thông tin chi phí";
                    await CreateHistoryAsync(
                        existingExpense.Id,
                        existingExpense.Status,
                        existingExpense.Status,
                        currentUser,
                        updateNote
                    );

                    result.Message = "Cập nhật chi phí thành công";
                }
                else
                {
                    // Thêm mới - sử dụng AutoMapper để map từ model
                    var expense = FinanceMappingExtensions.ToEntity(model);

                    // Set các giá trị mặc định cho tạo mới
                    expense.Id = Guid.NewGuid();
                    expense.Status = ExpenseStatus.Pending;
                    expense.RejectReason = null;
                    expense.CreatedTime = DateTimeHelper.CurrentTime();
                    expense.UpdatedTime = DateTimeHelper.CurrentTime();
                    expense.CreatedBy = currentUser.UserId;
                    expense.CreatedByUserName = currentUser.UserName;
                    expense.UpdatedBy = currentUser.UserId;
                    expense.UpdatedByUserName = currentUser.UserName;
                    expense.IsDeleted = false;
                    expense.ApprovedBy = expenseCategory.ApprovedBy;
                    // Copy thông tin ngân hàng nếu có UserBankAccountId
                    await CopyBankAccountInfo(expense, model.UserBankAccountId);

                    await _expenseRepository.InsertAsync(expense);

                    // Ghi lịch sử tạo mới (null -> Pending)
                    await CreateHistoryAsync(
                        expense.Id,
                        null,
                        ExpenseStatus.Pending,
                        currentUser,
                        "Tạo mới chi phí"
                    );

                    result.Message = "Tạo chi phí thành công";
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Copy thông tin ngân hàng từ UserBankAccount vào Expense (Copy-on-Reference Pattern)
        /// </summary>
        /// <param name="expense">Expense entity cần cập nhật</param>
        /// <param name="userBankAccountId">ID tài khoản ngân hàng</param>
        private async Task CopyBankAccountInfo(Expense expense, int? userBankAccountId)
        {
            if (userBankAccountId.HasValue)
            {
                var userBankAccount = await _userBankAccountRepository
                    .Query()
                    .Include(x => x.Bank)
                    .FirstOrDefaultAsync(x => x.Id == userBankAccountId.Value);

                if (userBankAccount != null)
                {
                    // Copy thông tin ngân hàng vào expense
                    expense.BankAccountNumber = userBankAccount.AccountNumber;
                    expense.BankAccountHolderName = userBankAccount.AccountHolderName;
                    expense.BankCode = userBankAccount.Bank?.BankCode ?? string.Empty;
                    expense.BankName = userBankAccount.Bank?.BrandName ?? string.Empty;
                    expense.BankBranchName = string.Empty; // Bank entity không có BranchName
                }
            }
            else
            {
                // Nếu không có UserBankAccountId, xóa thông tin ngân hàng
                expense.BankAccountNumber = string.Empty;
                expense.BankAccountHolderName = string.Empty;
                expense.BankCode = string.Empty;
                expense.BankName = string.Empty;
                expense.BankBranchName = string.Empty;
            }
        }

        #region CreateOrUpdate
        /// <summary>
        /// Tạo chi phí mới
        /// </summary>
        /// <param name="expense">Thông tin chi phí</param>
        /// <returns>Kết quả của thao tác</returns>
        private async Task<ExpenseResult> Create(Expense expense)
        {
            var result = new ExpenseResult();
            try
            {
                expense.Id = Guid.NewGuid();
                expense = expense.UpdateCommonGuid();

                await _expenseRepository.InsertAsync(expense);
                result.Id = expense.Id;
                result.Result = Result.Success;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = Guid.Empty;
            }
            return result;
        }

        /// <summary>
        /// Cập nhật chi phí (không thay đổi Status và RejectReason)
        /// </summary>
        /// <param name="expense">Thông tin chi phí</param>
        /// <returns>Kết quả của thao tác</returns>
        private async Task<ExpenseResult> Update(Expense expense)
        {
            var result = new ExpenseResult() { Result = Result.Success };
            var expenseForUpdate = await _expenseRepository.Query()
                .FirstOrDefaultAsync(e => e.Id == expense.Id);

            if (expenseForUpdate == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu!";
                return result;
            }

            try
            {
                // Chỉ cập nhật các thông tin cơ bản, không thay đổi Status và RejectReason
                expenseForUpdate.Description = expense.Description;
                expenseForUpdate.Note = expense.Note;
                expenseForUpdate.Amount = expense.Amount;
                expenseForUpdate.ExpenseCategoryId = expense.ExpenseCategoryId;
                expenseForUpdate.ApprovedBy = expense.ApprovedBy;
                // Không cập nhật: Status, RejectReason
                expenseForUpdate = expenseForUpdate.UpdateCommonGuid();

                await _expenseRepository.UpdateAsync(expenseForUpdate);
                result.Id = expenseForUpdate.Id;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }
        #endregion

        #region Approve/Reject
        /// <summary>
        /// Duyệt chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> Approve(Guid id, CurrentUser currentUser)
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID chi phí không hợp lệ";
                return result;
            }

            var expense = await _expenseRepository.Query()
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expense == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu";
                return result;
            }
            bool isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");

            // Kiểm tra quyền duyệt: chỉ người được phân quyền mới được duyệt
            if (!isFounder && expense.ApprovedBy.HasValue && expense.ApprovedBy.Value != currentUser.UserId)
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền duyệt chi phí này";
                return result;
            }

            if (expense.Status == ExpenseStatus.Approved)
            {
                result.Result = Result.Failed;
                result.Message = "Chi phí đã được duyệt trước đó";
                return result;
            }

            try
            {
                // Lưu trạng thái cũ trước khi thay đổi
                var oldStatus = expense.Status;

                expense.Status = ExpenseStatus.Approved;
                expense.RejectReason = null; // Xóa lý do từ chối nếu có
                expense.UpdatedTime = DateTimeHelper.CurrentTime();
                expense.UpdatedBy = currentUser.UserId;
                expense.UpdatedByUserName = currentUser.UserName;

                await _expenseRepository.UpdateAsync(expense);

                // Ghi lịch sử duyệt (Pending/Rejected -> Approved)
                await CreateHistoryAsync(
                    expense.Id,
                    oldStatus,
                    ExpenseStatus.Approved,
                    currentUser,
                    "Duyệt chi phí"
                );

                result.Result = Result.Success;
                result.Message = "Duyệt chi phí thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Bỏ duyệt chi phí (chuyển về trạng thái chờ duyệt)
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> Unapprove(Guid id, CurrentUser currentUser)
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID chi phí không hợp lệ";
                return result;
            }

            var expense = await _expenseRepository.Query()
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expense == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu";
                return result;
            }

            bool isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");

            // Kiểm tra quyền bỏ duyệt: chỉ người được phân quyền mới được bỏ duyệt
            if (!isFounder && expense.ApprovedBy.HasValue && expense.ApprovedBy.Value != currentUser.UserId)
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền bỏ duyệt chi phí này";
                return result;
            }

            if (expense.Status != ExpenseStatus.Approved)
            {
                result.Result = Result.Failed;
                result.Message = "Chỉ có thể bỏ duyệt chi phí đã được duyệt";
                return result;
            }

            try
            {
                // Lưu trạng thái cũ trước khi thay đổi
                var oldStatus = expense.Status;

                expense.Status = ExpenseStatus.Pending;
                expense.UpdatedTime = DateTimeHelper.CurrentTime();
                expense.UpdatedBy = currentUser.UserId;
                expense.UpdatedByUserName = currentUser.UserName;

                await _expenseRepository.UpdateAsync(expense);

                // Ghi lịch sử bỏ duyệt (Approved → Pending)
                await CreateHistoryAsync(
                    expense.Id,
                    oldStatus,
                    ExpenseStatus.Pending,
                    currentUser,
                    "Bỏ duyệt chi phí"
                );

                result.Result = Result.Success;
                result.Message = "Bỏ duyệt chi phí thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Từ chối chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="rejectReason">Lý do từ chối</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> Reject(Guid id, string rejectReason, CurrentUser currentUser)
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID chi phí không hợp lệ";
                return result;
            }

            if (string.IsNullOrWhiteSpace(rejectReason))
            {
                result.Result = Result.Failed;
                result.Message = "Lý do từ chối là bắt buộc";
                return result;
            }

            var expense = await _expenseRepository.Query()
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expense == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu";
                return result;
            }
            bool isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            // Kiểm tra quyền duyệt: chỉ người được phân quyền mới được từ chối
            if (!isFounder && expense.ApprovedBy.HasValue && expense.ApprovedBy.Value != currentUser.UserId)
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền từ chối chi phí này";
                return result;
            }

            if (expense.Status == ExpenseStatus.Rejected)
            {
                result.Result = Result.Failed;
                result.Message = "Chi phí đã bị từ chối trước đó";
                return result;
            }

            try
            {
                // Lưu trạng thái cũ trước khi thay đổi
                var oldStatus = expense.Status;

                expense.Status = ExpenseStatus.Rejected;
                expense.RejectReason = rejectReason.Trim();
                expense.UpdatedTime = DateTimeHelper.CurrentTime();
                expense.UpdatedBy = currentUser.UserId;
                expense.UpdatedByUserName = currentUser.UserName;

                await _expenseRepository.UpdateAsync(expense);

                // Ghi lịch sử từ chối (Pending/Approved -> Rejected)
                await CreateHistoryAsync(
                    expense.Id,
                    oldStatus,
                    ExpenseStatus.Rejected,
                    currentUser,
                    "Từ chối chi phí",
                    rejectReason
                );

                result.Result = Result.Success;
                result.Message = "Từ chối chi phí thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Đánh dấu chi phí đã chuyển tiền
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <param name="note">Ghi chú</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> MarkAsPaid(Guid id, CurrentUser currentUser, string note = "")
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID chi phí không hợp lệ";
                return result;
            }

            var expense = await _expenseRepository.Query()
                .Include(e => e.ExpenseCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expense == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu";
                return result;
            }

            // Kiểm tra trạng thái: chỉ chi phí đã approved mới được đánh dấu đã chuyển tiền
            if (expense.Status != ExpenseStatus.Approved)
            {
                result.Result = Result.Failed;
                result.Message = "Chỉ có thể chuyển tiền cho chi phí đã được duyệt";
                return result;
            }

            if (expense.Status == ExpenseStatus.Paid)
            {
                result.Result = Result.Failed;
                result.Message = "Chi phí đã được chuyển tiền trước đó";
                return result;
            }

            // Sử dụng transaction để đảm bảo tính nhất quán
            using (var dbTransaction = _walletRepository.BeginTransaction())
            {
                try
                {
                    // Lấy hoặc tạo ví cho user hiện tại
                    var wallet = await _walletRepository.Query()
                        .FirstOrDefaultAsync(w => w.UserId == currentUser.UserId && w.WalletType == WalletType.Personal);

                    if (wallet == null)
                    {
                        // Tạo ví mới nếu chưa có
                        wallet = new Wallet
                        {
                            UserId = currentUser.UserId,
                            Balance = 0,
                            WalletType = WalletType.Personal,
                            WalletStatus = WalletStatus.Active,
                            CreatedTime = DateTimeHelper.CurrentTime(),
                            UpdatedTime = DateTimeHelper.CurrentTime(),
                            CreatedBy = currentUser.UserId,
                            CreatedByUserName = currentUser.UserName,
                            UpdatedBy = currentUser.UserId,
                            UpdatedByUserName = currentUser.UserName,
                            IsDeleted = false
                        };
                        await _walletRepository.InsertAsync(wallet);
                    }

                    // Kiểm tra số dư ví
                    if (wallet.Balance < expense.Amount)
                    {
                        result.Result = Result.Failed;
                        result.Message = $"Số dư ví không đủ. Số dư hiện tại: {wallet.Balance:N0} VND, cần: {expense.Amount:N0} VND";
                        return result;
                    }

                    // Tạo giao dịch trừ tiền
                    var transaction = new Transaction
                    {
                        Id = Guid.NewGuid(),
                        Description = $"Chi phí: {expense.Description}",
                        Note = string.IsNullOrWhiteSpace(note) ? $"Chuyển tiền cho chi phí {expense.ExpenseCategory?.Name}" : note,
                        Amount = expense.Amount,
                        CashAmount = 0,
                        TransferAmount = expense.Amount,
                        WalletId = wallet.Id,
                        TransactionType = TransactionType.Withdraw,
                        TransactionDirection = TransactionDirection.Outcome,
                        TransactionDate = DateTimeOffset.Now,
                        FromUserId = currentUser.UserId,
                        ExpenseId = expense.Id,
                        CreatedTime = DateTimeHelper.CurrentTime(),
                        UpdatedTime = DateTimeHelper.CurrentTime(),
                        CreatedBy = currentUser.UserId,
                        CreatedByUserName = currentUser.UserName,
                        UpdatedBy = currentUser.UserId,
                        UpdatedByUserName = currentUser.UserName,
                        IsDeleted = false
                    };

                    await _transactionRepository.InsertAsync(transaction);

                    // Cập nhật số dư ví
                    wallet.Balance -= expense.Amount;
                    await _walletRepository.UpdateAsync(wallet);

                    // Cập nhật trạng thái expense
                    expense.Status = ExpenseStatus.Paid;
                    expense.UpdatedTime = DateTimeHelper.CurrentTime();
                    expense.UpdatedBy = currentUser.UserId;
                    expense.UpdatedByUserName = currentUser.UserName;
                    await _expenseRepository.UpdateAsync(expense);

                    // Ghi lịch sử chuyển tiền (Approved -> Paid)
                    await CreateHistoryAsync(
                        expense.Id,
                        ExpenseStatus.Approved,
                        ExpenseStatus.Paid,
                        currentUser,
                        note ?? "Chuyển tiền cho chi phí"
                    );

                    await dbTransaction.CommitAsync();

                    result.Result = Result.Success;
                    result.Message = $"Đã chuyển tiền thành công. Số tiền: {expense.Amount:N0} VND";
                }
                catch (Exception e)
                {
                    await dbTransaction.RollbackAsync();
                    result.Result = Result.SystemError;
                    result.Message = $"Lỗi khi thực hiện giao dịch: {e.Message}";
                }
            }

            return result;
        }
        #endregion

        /// <summary>
        /// Xóa chi phí
        /// </summary>
        /// <param name="id">ID chi phí</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Kết quả của thao tác</returns>
        public async Task<BaseResult> Delete(Guid id, CurrentUser currentUser)
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "Yêu cầu xóa chi phí không hợp lệ";
                return result;
            }

            var expenseForUpdate = await _expenseRepository.Query()
                .FirstOrDefaultAsync(e => e.Id == id);

            if (expenseForUpdate == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy chi phí yêu cầu";
                return result;
            }

            try
            {
                // Soft delete
                expenseForUpdate.IsDeleted = true;
                expenseForUpdate.UpdatedTime = DateTimeHelper.CurrentTime();
                expenseForUpdate.UpdatedBy = currentUser.UserId;
                expenseForUpdate.UpdatedByUserName = currentUser.UserName;

                await _expenseRepository.UpdateAsync(expenseForUpdate);
                result.Result = Result.Success;
                result.Message = "Xóa chi phí thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }
            return result;
        }

        /// <summary>
        /// Tính toán các quyền cho ExpenseItem
        /// </summary>
        /// <param name="expenseItem">ExpenseItem cần tính toán quyền</param>
        /// <param name="expense">Expense entity</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        private async Task CalculatePermissions(ExpenseItem expenseItem, Expense expense, CurrentUser currentUser)
        {
            try
            {
                // Check if user is Founder
                bool isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");


                // Kiểm tra quyền MarkAsPaid - dựa vào role Expense.MarkAsPaid
                expenseItem.CanMarkAsPaid = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.MarkAsPaid");

                // Kiểm tra quyền duyệt/từ chối - dựa vào ExpenseCategory.ApprovedBy
                if (expense.ExpenseCategory != null)
                {
                    // User có thể duyệt/từ chối nếu:
                    // 1. Là người được chỉ định duyệt cho ExpenseCategory này (ExpenseCategory.ApprovedBy)
                    // 2. Hoặc có quyền Expense.Approve/Expense.Reject
                    var canApproveByCategory = expense.ExpenseCategory.ApprovedBy == currentUser.UserId;
                    var canApproveByRole = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.Approve");
                    var canRejectByRole = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.Reject");

                    expenseItem.CanApprove = isFounder || (canApproveByCategory && canApproveByRole);
                    expenseItem.CanReject = isFounder || (canApproveByCategory && canRejectByRole);
                }
                else
                {
                    // Nếu không có ExpenseCategory, chỉ kiểm tra role
                    expenseItem.CanApprove = isFounder || await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.Approve");
                    expenseItem.CanReject = isFounder || await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.Reject");
                }
            }
            catch (Exception)
            {
                // Nếu có lỗi khi kiểm tra quyền, set tất cả về false để đảm bảo an toàn
                expenseItem.CanApprove = false;
                expenseItem.CanReject = false;
                expenseItem.CanMarkAsPaid = false;
            }
        }

        /// <summary>
        /// Áp dụng filter quyền xem cho query
        /// </summary>
        /// <param name="query">Query gốc</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>Query đã được filter theo quyền xem</returns>
        private async Task<IQueryable<Expense>> ApplyViewPermissionsFilter(IQueryable<Expense> query, CurrentUser currentUser)
        {
            // Kiểm tra nếu user là Founder hoặc có quyền Expense.MarkAsPaid
            var isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            var canMarkAsPaid = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.MarkAsPaid");

            if (isFounder || canMarkAsPaid)
            {
                // Founder và người có quyền MarkAsPaid được xem tất cả
                return query;
            }

            // Người thường chỉ xem được chi phí do mình tạo hoặc do mình duyệt
            return query.Where(e => e.CreatedBy == currentUser.UserId ||
                                   (e.ExpenseCategory != null && e.ExpenseCategory.ApprovedBy == currentUser.UserId));
        }

        /// <summary>
        /// Kiểm tra quyền xem một chi phí cụ thể
        /// </summary>
        /// <param name="expense">Chi phí cần kiểm tra</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <returns>True nếu có quyền xem</returns>
        private async Task<bool> HasViewPermission(Expense expense, CurrentUser currentUser)
        {
            // Kiểm tra nếu user là Founder hoặc có quyền Expense.MarkAsPaid
            var isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            var canMarkAsPaid = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Expense.MarkAsPaid");

            if (isFounder || canMarkAsPaid)
            {
                // Founder và người có quyền MarkAsPaid được xem tất cả
                return true;
            }

            // Người thường chỉ xem được chi phí do mình tạo hoặc do mình duyệt
            return expense.CreatedBy == currentUser.UserId ||
                   (expense.ExpenseCategory != null && expense.ExpenseCategory.ApprovedBy == currentUser.UserId);
        }

        /// <summary>
        /// Tạo lịch sử thay đổi trạng thái chi phí
        /// </summary>
        /// <param name="expenseId">ID của chi phí</param>
        /// <param name="oldStatus">Trạng thái trước khi thay đổi</param>
        /// <param name="newStatus">Trạng thái sau khi thay đổi</param>
        /// <param name="currentUser">Người dùng hiện tại</param>
        /// <param name="note">Ghi chú</param>
        /// <param name="reason">Lý do (dùng cho từ chối)</param>
        private async Task CreateHistoryAsync(
            Guid expenseId,
            ExpenseStatus? oldStatus,
            ExpenseStatus newStatus,
            CurrentUser currentUser,
            string? note = null,
            string? reason = null)
        {
            var history = new ExpenseHistory
            {
                ExpenseId = expenseId,
                OldStatus = oldStatus,
                NewStatus = newStatus,
                Note = note,
                Reason = reason,
                CreatedTime = DateTimeHelper.CurrentTime(),
                CreatedBy = currentUser.UserId,
                CreatedByUserName = currentUser.UserName,
                UpdatedTime = DateTimeHelper.CurrentTime(),
                UpdatedBy = currentUser.UserId,
                UpdatedByUserName = currentUser.UserName,
                IsDeleted = false
            };

            await _expenseHistoryRepository.InsertAsync(history);
        }
    }
}