using Lada.Framework.Data.Domains.Finance;
using Lada.Framework.Data.Enums;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures;
using Ladaer.BackEnd.Infrastructures.DTO.Items.FuelCards;
using Ladaer.BackEnd.Infrastructures.DTO.Models.FuelCards;
using Ladaer.BackEnd.Infrastructures.DTO.Results.FuelCards;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.FuelCards;

/// <summary>
/// Interface cho service quản lý thẻ xăng dầu (thẻ tín dụng)
/// </summary>
public interface IFuelCardService
{
    /// <summary>
    /// Tìm kiếm thẻ xăng dầu với phân trang
    /// </summary>
    Task<SmartTableResult<FuelCardItem>> Search(SmartTableParam param);

    /// <summary>
    /// Lấy thẻ xăng dầu theo ID
    /// </summary>
    Task<FuelCardItem?> GetByIdAsync(int id);

    /// <summary>
    /// Tạo hoặc cập nhật thẻ xăng dầu
    /// </summary>
    Task<BaseResult> CreateOrUpdateAsync(FuelCardModel model, CurrentUser currentUser);

    /// <summary>
    /// Xóa thẻ xăng dầu
    /// </summary>
    Task<BaseResult> DeleteAsync(int id, CurrentUser currentUser);

    /// <summary>
    /// Lấy danh sách thẻ đang hoạt động
    /// </summary>
    Task<List<FuelCardItem>> GetActiveCardsAsync();

    /// <summary>
    /// Lấy tổng nợ thẻ tín dụng chưa thanh toán cho ngân hàng
    /// </summary>
    Task<decimal> GetTotalDebtAsync();
}

/// <summary>
/// Service quản lý thẻ xăng dầu (thẻ tín dụng)
/// </summary>
public class FuelCardService : IFuelCardService
{
    private readonly IRepository<FuelCard> _fuelCardRepository;

    public FuelCardService(
        IRepository<FuelCard> fuelCardRepository)
    {
        _fuelCardRepository = fuelCardRepository;
    }

    public async Task<SmartTableResult<FuelCardItem>> Search(SmartTableParam param)
    {
        param ??= new SmartTableParam();

        var query = _fuelCardRepository.Query()
            .Include(x => x.ResponsibleUser)
            .Where(x => !x.IsDeleted);

        // Search by card number or holder name
        if (param.Search?.PredicateObject != null)
        {
            dynamic search = param.Search.PredicateObject;
            if (search.Keyword != null)
            {
                string keyword = search.Keyword.ToString().ToLower().Trim();
                if (!string.IsNullOrEmpty(keyword))
                {
                    query = query.Where(x =>
                        x.CardNumber.ToLower().Contains(keyword) ||
                        x.CardholderName.ToLower().Contains(keyword) ||
                        x.BankName.ToLower().Contains(keyword));
                }
            }
        }

        var totalRecords = await query.CountAsync();

        // Apply sorting
        if (!string.IsNullOrWhiteSpace(param.Sort?.Predicate))
        {
            query = param.Sort.Predicate.ToLower() switch
            {
                "cardnumber" => param.Sort.Reverse ? query.OrderByDescending(x => x.CardNumber) : query.OrderBy(x => x.CardNumber),
                "status" => param.Sort.Reverse ? query.OrderByDescending(x => x.Status) : query.OrderBy(x => x.Status),
                "currentdebt" => param.Sort.Reverse ? query.OrderByDescending(x => x.CurrentDebt) : query.OrderBy(x => x.CurrentDebt),
                _ => query.OrderByDescending(x => x.CreatedTime)
            };
        }
        else
        {
            query = query.OrderByDescending(x => x.CreatedTime);
        }

        // Apply paging
        var items = await query
            .Skip(param.Pagination.Start)
            .Take(param.Pagination.PageSize)
            .Select(x => new FuelCardItem
            {
                Id = x.Id,
                CardNumber = x.CardNumber,
                CardholderName = x.CardholderName,
                BankName = x.BankName,
                CardType = x.CardType,
                ResponsibleUserId = x.ResponsibleUserId,
                ResponsibleUserName = x.ResponsibleUser != null ? x.ResponsibleUser.UserName : null,
                Status = x.Status,
                ExpiryDate = x.ExpiryDate,
                CreditLimit = x.CreditLimit,
                CurrentDebt = x.CurrentDebt,
                Notes = x.Notes,
                CreatedTime = x.CreatedTime,
                UpdatedTime = x.UpdatedTime
            })
            .ToListAsync();

        return new SmartTableResult<FuelCardItem>
        {
            Items = items,
            TotalRecord = totalRecords,
            NumberOfPages = (int)Math.Ceiling((double)totalRecords / param.Pagination.PageSize)
        };
    }

    public async Task<FuelCardItem?> GetByIdAsync(int id)
    {
        var entity = await _fuelCardRepository.Query()
            .Include(x => x.ResponsibleUser)
            .FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);

        if (entity == null) return null;

        return new FuelCardItem
        {
            Id = entity.Id,
            CardNumber = entity.CardNumber,
            CardholderName = entity.CardholderName,
            BankName = entity.BankName,
            CardType = entity.CardType,
            ResponsibleUserId = entity.ResponsibleUserId,
            ResponsibleUserName = entity.ResponsibleUser?.UserName,
            Status = entity.Status,
            ExpiryDate = entity.ExpiryDate,
            CreditLimit = entity.CreditLimit,
            CurrentDebt = entity.CurrentDebt,
            Notes = entity.Notes,
            CreatedTime = entity.CreatedTime,
            UpdatedTime = entity.UpdatedTime
        };
    }

    public async Task<BaseResult> CreateOrUpdateAsync(FuelCardModel model, CurrentUser currentUser)
    {
        var result = new BaseResult();

        try
        {
            // Validate card number uniqueness
            var existingCard = await _fuelCardRepository.Query()
                .FirstOrDefaultAsync(x => x.CardNumber == model.CardNumber && x.Id != model.Id && !x.IsDeleted);

            if (existingCard != null)
            {
                result.Message = "Số thẻ đã tồn tại trong hệ thống";
                return result;
            }

            // Note: Driver existence is validated by foreign key constraint

            FuelCard entity;
            if (model.Id > 0)
            {
                // Update
                entity = await _fuelCardRepository.Query()
                    .FirstOrDefaultAsync(x => x.Id == model.Id && !x.IsDeleted);

                if (entity == null)
                {
                    result.Message = "Không tìm thấy thẻ xăng dầu";
                    return result;
                }

                entity.CardNumber = model.CardNumber;
                entity.CardholderName = model.CardholderName;
                entity.BankName = model.BankName;
                entity.CardType = model.CardType;
                entity.ResponsibleUserId = model.ResponsibleUserId;
                entity.Status = model.Status;
                entity.ExpiryDate = model.ExpiryDate;
                entity.CreditLimit = model.CreditLimit;
                entity.Notes = model.Notes;
                entity.UpdatedTime = DateTimeOffset.Now;
                entity.UpdatedBy = currentUser.UserId;
                entity.UpdatedByUserName = currentUser.UserName;

                await _fuelCardRepository.UpdateAsync(entity);
                result.Message = "Cập nhật thẻ xăng dầu thành công";
            }
            else
            {
                // Create
                entity = new FuelCard
                {
                    CardNumber = model.CardNumber,
                    CardholderName = model.CardholderName,
                    BankName = model.BankName,
                    CardType = model.CardType,
                    ResponsibleUserId = model.ResponsibleUserId,
                    Status = model.Status,
                    ExpiryDate = model.ExpiryDate,
                    CreditLimit = model.CreditLimit,
                    CurrentDebt = 0,
                    Notes = model.Notes,
                    CreatedTime = DateTimeOffset.Now,
                    CreatedBy = currentUser.UserId,
                    CreatedByUserName = currentUser.UserName,
                    IsDeleted = false
                };

                await _fuelCardRepository.InsertAsync(entity);
                result.Message = "Tạo thẻ xăng dầu thành công";
            }

            result.Result = Result.Success;
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

    public async Task<BaseResult> DeleteAsync(int id, CurrentUser currentUser)
    {
        var result = new BaseResult();

        try
        {
            var entity = await _fuelCardRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);

            if (entity == null)
            {
                result.Message = "Không tìm thấy thẻ xăng dầu";
                return result;
            }

            // Check if card has transactions
            var hasTransactions = await _fuelCardRepository.Query()
                .Where(x => x.Id == id)
                .SelectMany(x => x.FuelCardTransactions)
                .AnyAsync();

            if (hasTransactions)
            {
                result.Message = "Không thể xóa thẻ đã có giao dịch";
                return result;
            }

            entity.IsDeleted = true;
            entity.UpdatedTime = DateTimeOffset.Now;
            entity.UpdatedBy = currentUser.UserId;
            entity.UpdatedByUserName = currentUser.UserName;

            await _fuelCardRepository.UpdateAsync(entity);

            result.Result = Result.Success;
            result.Message = "Xóa thẻ xăng dầu thành công";
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }



    public async Task<List<FuelCardItem>> GetActiveCardsAsync()
    {
        return await _fuelCardRepository.Query()
            .Include(x => x.ResponsibleUser)
            .Where(x => !x.IsDeleted && x.Status == FuelCardStatus.Active)
            .OrderBy(x => x.CardNumber)
            .Select(x => new FuelCardItem
            {
                Id = x.Id,
                CardNumber = x.CardNumber,
                CardholderName = x.CardholderName,
                BankName = x.BankName,
                CardType = x.CardType,
                ResponsibleUserId = x.ResponsibleUserId,
                ResponsibleUserName = x.ResponsibleUser != null ? x.ResponsibleUser.UserName : null,
                Status = x.Status,
                ExpiryDate = x.ExpiryDate,
                CreditLimit = x.CreditLimit,
                CurrentDebt = x.CurrentDebt,
                Notes = x.Notes
            })
            .ToListAsync();
    }

    public async Task<decimal> GetTotalDebtAsync()
    {
        return await _fuelCardRepository.Query()
            .Where(x => !x.IsDeleted)
            .SumAsync(x => x.CurrentDebt);
    }
}
