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 IncomeStatus = Lada.Framework.Data.Enums.IncomeStatus;

namespace Ladaer.BackEnd.Infrastructures.Services.Finances
{
    /// <summary>
    /// Interface cho service quản lý doanh thu
    /// </summary>
    public interface IIncomeService
    {
        /// <summary>
        /// Tìm kiếm doanh thu
        /// </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<IncomeItem>> Search(SmartTableParam param, CurrentUser currentUser);

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

        /// <summary>
        /// Tạo mới hoặc cập nhật doanh thu
        /// </summary>
        /// <param name="model">Thông tin doanh thu</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(IncomeModel model, CurrentUser currentUser);

        /// <summary>
        /// Duyệt doanh thu
        /// </summary>
        /// <param name="id">ID doanh thu</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>
        /// Từ chối doanh thu
        /// </summary>
        /// <param name="id">ID doanh thu</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 doanh thu đã nhận tiền
        /// </summary>
        /// <param name="id">ID doanh thu</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 nhận tiền</returns>
        Task<BaseResult> MarkAsReceived(Guid id, CurrentUser currentUser, string note = "");

        /// <summary>
        /// Xóa doanh thu
        /// </summary>
        /// <param name="id">ID doanh thu</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ý doanh thu
    /// </summary>
    public class IncomeService : IIncomeService
    {
        private readonly IRepository<Income> _incomeRepository;
        private readonly IRepository<IncomeCategory> _incomeCategoryRepository;
        private readonly IUserRepository<User> _userRepository;
        private readonly IRepository<Wallet> _walletRepository;
        private readonly IRepository<Transaction> _transactionRepository;
        private readonly IPermissionService _permissionService;

        /// <summary>
        /// Khởi tạo một thể hiện của <see cref="IncomeService"/>
        /// </summary>
        public IncomeService(
            IRepository<Income> incomeRepository,
            IRepository<IncomeCategory> incomeCategoryRepository,
            IUserRepository<User> userRepository,
            IRepository<Wallet> walletRepository,
            IRepository<Transaction> transactionRepository,
            IPermissionService permissionService)
        {
            _incomeRepository = incomeRepository;
            _incomeCategoryRepository = incomeCategoryRepository;
            _userRepository = userRepository;
            _walletRepository = walletRepository;
            _transactionRepository = transactionRepository;
            _permissionService = permissionService;
        }

        /// <summary>
        /// Tìm kiếm doanh thu
        /// </summary>
        public async Task<SmartTableResult<IncomeItem>> Search(SmartTableParam param, CurrentUser currentUser)
        {
            IQueryable<Income> query = _incomeRepository.Query()
                .Include(e => e.IncomeCategory);

            // Kiểm tra quyền xem doanh thu
            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.IncomeCategoryId != null && search.IncomeCategoryId > 0)
                {
                    int categoryId = search.IncomeCategoryId;
                    query = query.Where(x => x.IncomeCategoryId == categoryId);
                }

                if (search.Status != null)
                {
                    IncomeStatus 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;
                    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 };

            var result = await query.Include(e => e.IncomeCategory)
                .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
                var incomeIds = result.Items.Select(x => x.Id).ToList();
                var incomes = await _incomeRepository.Query()
                    .Include(e => e.IncomeCategory)
                    .Where(e => incomeIds.Contains(e.Id))
                    .ToListAsync();

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

            return result;
        }

        /// <summary>
        /// Lấy thông tin chi tiết của doanh thu
        /// </summary>
        public async Task<IncomeItem?> GetById(Guid id, CurrentUser currentUser)
        {
            if (id == Guid.Empty)
            {
                return null;
            }

            var income = await _incomeRepository.Query()
                .Include(e => e.IncomeCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

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

            // Kiểm tra quyền xem
            if (!await HasViewPermission(income, currentUser))
            {
                return null;
            }

            var incomeItem = FinanceMappingExtensions.ToItem(income);
            await CalculatePermissions(incomeItem, income, currentUser);

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

            return incomeItem;
        }

        /// <summary>
        /// Tạo mới hoặc cập nhật doanh thu
        /// </summary>
        public async Task<BaseResult> CreateOrUpdate(IncomeModel model, CurrentUser currentUser)
        {
            var result = new BaseResult { Result = Result.Success };

            try
            {
                // Lấy thông tin IncomeCategory để lấy ApprovedBy mặc định
                var incomeCategory = await _incomeCategoryRepository.Query()
                    .FirstOrDefaultAsync(c => c.Id == model.IncomeCategoryId);

                if (incomeCategory == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy danh mục doanh thu!";
                    return result;
                }

                if (model.Id != Guid.Empty)
                {
                    // Cập nhật
                    var existingIncome = await _incomeRepository.Query()
                        .FirstOrDefaultAsync(e => e.Id == model.Id);

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

                    existingIncome.Description = model.Description;
                    existingIncome.Note = model.Note;
                    existingIncome.Amount = model.Amount;
                    existingIncome.IncomeCategoryId = model.IncomeCategoryId;
                    existingIncome.ApprovedBy = incomeCategory.ApprovedBy;
                    existingIncome.UpdatedTime = DateTimeHelper.CurrentTime();
                    existingIncome.UpdatedBy = currentUser.UserId;
                    existingIncome.UpdatedByUserName = currentUser.UserName;

                    await _incomeRepository.UpdateAsync(existingIncome);
                    result.Message = "Cập nhật doanh thu thành công";
                }
                else
                {
                    // Tạo mới
                    var income = model.ToEntity();
                    income.Id = Guid.NewGuid();
                    income.Status = IncomeStatus.Pending;
                    income.ApprovedBy = incomeCategory.ApprovedBy;
                    income.CreatedTime = DateTimeHelper.CurrentTime();
                    income.UpdatedTime = DateTimeHelper.CurrentTime();
                    income.CreatedBy = currentUser.UserId;
                    income.CreatedByUserName = currentUser.UserName;
                    income.UpdatedBy = currentUser.UserId;
                    income.UpdatedByUserName = currentUser.UserName;

                    await _incomeRepository.InsertAsync(income);
                    result.Message = "Tạo doanh thu thành công";
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Duyệt doanh thu
        /// </summary>
        public async Task<BaseResult> Approve(Guid id, CurrentUser currentUser)
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID doanh thu không hợp lệ";
                return result;
            }

            var income = await _incomeRepository.Query()
                .Include(e => e.IncomeCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (income == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy doanh thu";
                return result;
            }

            if (income.Status != IncomeStatus.Pending)
            {
                result.Result = Result.Failed;
                result.Message = "Chỉ có thể duyệt doanh thu đang chờ xử lý";
                return result;
            }

            // Kiểm tra quyền duyệt
            if (!await HasApprovePermission(income, currentUser))
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền duyệt doanh thu này";
                return result;
            }

            try
            {
                // Cập nhật trạng thái
                income.Status = IncomeStatus.Approved;
                income.ApprovedBy = currentUser.UserId;
                income.UpdatedTime = DateTimeHelper.CurrentTime();
                income.UpdatedBy = currentUser.UserId;
                income.UpdatedByUserName = currentUser.UserName;

                // Cập nhật Income
                await _incomeRepository.UpdateAsync(income);

                // Tạo lịch sử
                await CreateIncomeHistory(income.Id, IncomeStatus.Approved, currentUser);

                result.Result = Result.Success;
                result.Message = "Duyệt doanh thu thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Từ chối doanh thu
        /// </summary>
        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 doanh thu không hợp lệ";
                return result;
            }

            if (string.IsNullOrWhiteSpace(rejectReason))
            {
                result.Result = Result.Failed;
                result.Message = "Lý do từ chối không được để trống";
                return result;
            }

            var income = await _incomeRepository.Query()
                .Include(e => e.IncomeCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (income == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy doanh thu";
                return result;
            }

            if (income.Status != IncomeStatus.Pending)
            {
                result.Result = Result.Failed;
                result.Message = "Chỉ có thể từ chối doanh thu đang chờ xử lý";
                return result;
            }

            // Kiểm tra quyền từ chối
            if (!await HasRejectPermission(income, currentUser))
            {
                result.Result = Result.Failed;
                result.Message = "Bạn không có quyền từ chối doanh thu này";
                return result;
            }

            try
            {
                income.Status = IncomeStatus.Rejected;
                income.RejectReason = rejectReason;
                income.ApprovedBy = currentUser.UserId;
                income.UpdatedTime = DateTimeHelper.CurrentTime();
                income.UpdatedBy = currentUser.UserId;
                income.UpdatedByUserName = currentUser.UserName;

                // Tạo lịch sử
                await CreateIncomeHistory(income.Id, IncomeStatus.Rejected, currentUser, rejectReason);

                await _incomeRepository.UpdateAsync(income);

                result.Result = Result.Success;
                result.Message = "Từ chối doanh thu thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Đánh dấu doanh thu đã nhận tiền
        /// </summary>
        public async Task<BaseResult> MarkAsReceived(Guid id, CurrentUser currentUser, string note = "")
        {
            var result = new BaseResult();
            if (id == Guid.Empty)
            {
                result.Result = Result.Failed;
                result.Message = "ID doanh thu không hợp lệ";
                return result;
            }

            var income = await _incomeRepository.Query()
                .Include(e => e.IncomeCategory)
                .FirstOrDefaultAsync(e => e.Id == id);

            if (income == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy doanh thu";
                return result;
            }

            if (income.Status != IncomeStatus.Approved)
            {
                result.Result = Result.Failed;
                result.Message = "Chỉ có thể đánh dấu nhận tiền cho doanh thu đã được phê duyệt";
                return result;
            }

            try
            {
                using var dbTransaction = _walletRepository.BeginTransaction();

                // Lấy ví của user
                var wallet = await _walletRepository.Query()
                    .FirstOrDefaultAsync(w => w.UserId == currentUser.UserId);

                if (wallet == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy ví của bạn";
                    return result;
                }

                // Tạo giao dịch cộng tiền
                var transaction = new Transaction
                {
                    Id = Guid.NewGuid(),
                    Description = $"Doanh thu: {income.Description}",
                    Note = string.IsNullOrWhiteSpace(note) ? $"Nhận tiền doanh thu {income.IncomeCategory?.Name}" : note,
                    Amount = income.Amount,
                    CashAmount = 0,
                    TransferAmount = income.Amount,
                    WalletId = wallet.Id,
                    TransactionType = TransactionType.Recharge,
                    TransactionDirection = TransactionDirection.Income,
                    TransactionDate = DateTimeOffset.Now,
                    FromUserId = currentUser.UserId,
                    IncomeId = income.Id, // Link với Income
                    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 += income.Amount;
                await _walletRepository.UpdateAsync(wallet);

                // Cập nhật trạng thái income
                income.Status = IncomeStatus.Received;
                income.TransactionId = transaction.Id;
                income.UpdatedTime = DateTimeHelper.CurrentTime();
                income.UpdatedBy = currentUser.UserId;
                income.UpdatedByUserName = currentUser.UserName;
                await _incomeRepository.UpdateAsync(income);

                // Tạo lịch sử
                await CreateIncomeHistory(income.Id, IncomeStatus.Received, currentUser, note);

                await dbTransaction.CommitAsync();

                result.Result = Result.Success;
                result.Message = "Đánh dấu nhận tiền thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Xóa doanh thu
        /// </summary>
        public async Task<BaseResult> Delete(Guid id, CurrentUser currentUser)
        {
            var result = new BaseResult { Result = Result.Success };

            try
            {
                var income = await _incomeRepository.Query()
                    .FirstOrDefaultAsync(e => e.Id == id);

                if (income == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy doanh thu";
                    return result;
                }

                // Chỉ cho phép xóa nếu status là Pending hoặc Rejected
                if (income.Status == IncomeStatus.Approved || income.Status == IncomeStatus.Received)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không thể xóa doanh thu đã được duyệt hoặc đã nhận tiền";
                    return result;
                }

                income.IsDeleted = true;
                income.UpdatedTime = DateTimeHelper.CurrentTime();
                income.UpdatedBy = currentUser.UserId;
                income.UpdatedByUserName = currentUser.UserName;

                await _incomeRepository.UpdateAsync(income);

                result.Message = "Xóa doanh thu thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi hệ thống: {ex.Message}";
            }

            return result;
        }

        #region Private Methods

        /// <summary>
        /// Áp dụng filter theo quyền xem
        /// </summary>
        private async Task<IQueryable<Income>> ApplyViewPermissionsFilter(IQueryable<Income> query, CurrentUser currentUser)
        {
            // Nếu là Founder hoặc có quyền xem tất cả thì không filter
            var isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            var canSearch = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Income.Search");

            if (isFounder || canSearch)
            {
                return query;
            }

            // Nếu không có quyền thì chỉ xem được của chính mình
            query = query.Where(x => x.CreatedBy == currentUser.UserId);
            return query;
        }

        /// <summary>
        /// Kiểm tra quyền xem doanh thu
        /// </summary>
        private async Task<bool> HasViewPermission(Income income, CurrentUser currentUser)
        {
            var isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            var canSearch = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Income.Search");

            if (isFounder || canSearch)
            {
                return true;
            }

            // Chỉ xem được doanh thu do chính mình tạo
            return income.CreatedBy == currentUser.UserId;
        }

        /// <summary>
        /// Kiểm tra quyền duyệt doanh thu
        /// </summary>
        private async Task<bool> HasApprovePermission(Income income, CurrentUser currentUser)
        {
            var isFounder = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Founder");
            var canApprove = await _permissionService.UserHasRoleAsync(currentUser.UserId, "Income.Approve");

            // Nếu là Founder hoặc có quyền Income.Approve
            if (isFounder || canApprove)
            {
                return true;
            }

            // Hoặc là người được chỉ định để duyệt loại doanh thu này
            return income.IncomeCategory.ApprovedBy == currentUser.UserId;
        }

        /// <summary>
        /// Kiểm tra quyền từ chối doanh thu
        /// </summary>
        private async Task<bool> HasRejectPermission(Income income, CurrentUser currentUser)
        {
            // Tương tự như duyệt
            return await HasApprovePermission(income, currentUser);
        }

        /// <summary>
        /// Tính toán permissions cho từng item
        /// </summary>
        private async Task CalculatePermissions(IncomeItem item, Income income, CurrentUser currentUser)
        {
            item.CanApprove = income.Status == IncomeStatus.Pending && await HasApprovePermission(income, currentUser);
            item.CanReject = income.Status == IncomeStatus.Pending && await HasRejectPermission(income, currentUser);
            item.CanMarkAsReceived = income.Status == IncomeStatus.Approved && await HasApprovePermission(income, currentUser);
        }

        /// <summary>
        /// Tạo lịch sử doanh thu
        /// </summary>
        private async Task CreateIncomeHistory(Guid incomeId, IncomeStatus status, CurrentUser currentUser, string reason = "")
        {
            var history = new IncomeHistory
            {
                IncomeId = incomeId,
                Status = status,
                Reason = reason,
                Note = $"Thay đổi trạng thái: {status}",
                CreatedTime = DateTimeHelper.CurrentTime(),
                UpdatedTime = DateTimeHelper.CurrentTime(),
                CreatedBy = currentUser.UserId,
                CreatedByUserName = currentUser.UserName,
                UpdatedBy = currentUser.UserId,
                UpdatedByUserName = currentUser.UserName,
                IsDeleted = false
            };

            await _incomeRepository.Query()
                .FirstOrDefaultAsync(x => x.GetType() == typeof(IncomeHistory));

            // TODO: Implement history save logic
        }

        #endregion
    }
}

