using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Domains.Finance;
using Lada.Framework.Data.Domains.Medias;
using Lada.Framework.Data.Domains.Trucks;
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 Lada.Framework.Infrastructures.Services;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.FuelCards;
using Ladaer.BackEnd.Infrastructures.DTO.Models.FuelCards;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Trucks;
using Ladaer.BackEnd.Infrastructures.Services.Trucks;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.FuelCards;

/// <summary>
/// Interface cho service quản lý việc đổ dầu
/// </summary>
public interface IFuelRefillService
{
    /// <summary>
    /// Tạo hoặc cập nhật thông tin đổ dầu
    /// </summary>
    Task<BaseResult> CreateOrUpdate(FuelRefillModel model, CurrentUser currentUser);

    /// <summary>
    /// Lái xe đổ dầu - Upload ảnh và tự động tính chênh lệch định mức khoán
    /// </summary>
    [Obsolete("Sử dụng CreateOrUpdate thay thế")]
    Task<BaseResult> RefillFuelAsync(FuelRefillModel model, CurrentUser currentUser);

    /// <summary>
    /// Tìm kiếm lịch sử đổ dầu
    /// </summary>
    Task<SmartTableResult<FuelRefillItem>> Search(SmartTableParam param);

    /// <summary>
    /// Lấy chi tiết lần đổ dầu
    /// </summary>
    Task<FuelRefillItem?> GetByIdAsync(int id);

    /// <summary>
    /// Lấy lịch sử đổ dầu theo xe
    /// </summary>
    Task<List<FuelRefillItem>> GetByTruckAsync(int truckId);

    /// <summary>
    /// Lấy lịch sử đổ dầu theo lái xe
    /// </summary>
    Task<List<FuelRefillItem>> GetByDriverAsync(int driverId);

    /// <summary>
    /// Cập nhật thông tin đổ dầu
    /// </summary>
    [Obsolete("Sử dụng CreateOrUpdate thay thế")]
    Task<BaseResult> UpdateRefillAsync(FuelRefillUpdateModel model, CurrentUser currentUser);

    /// <summary>
    /// Xóa bản ghi đổ dầu
    /// </summary>
    Task<BaseResult> DeleteAsync(int id, CurrentUser currentUser);

    /// <summary>
    /// Đổ dầu cho lái xe trên app mobile.
    /// Tự động xác định xe từ CurrentDriverId, lấy PreviousOdo từ LastRefillOdo.
    /// </summary>
    Task<BaseResult> DriverFuelRefill(DriverFuelRefillModel model, CurrentUser currentUser);

    /// <summary>
    /// Tìm kiếm lịch sử đổ dầu theo lái xe (có phân trang, lọc ngày, từ khóa)
    /// </summary>
    Task<SmartTableResult<FuelRefillItem>> SearchByDriverAsync(int driverId, SmartTableParam param);
}

/// <summary>
/// Service quản lý việc đổ dầu với tính toán định mức khoán
/// </summary>
public class FuelRefillService : IFuelRefillService
{
    private readonly IRepository<FuelRefill> _fuelRefillRepository;
    private readonly IRepository<Truck> _truckRepository;
    private readonly IRepository<FuelCard> _fuelCardRepository;
    private readonly IRepository<FuelRefillMedia> _fuelRefillMediaRepository;
    private readonly IRepository<Media> _mediaRepository;
    private readonly IRepository<FuelCardTransaction> _transactionRepository;
    private readonly IUnifiedMediaService _unifiedMediaService;
    private readonly ITruckService _truckService;

    public FuelRefillService(
        IRepository<FuelRefill> fuelRefillRepository,
        IRepository<Truck> truckRepository,
        IRepository<FuelCard> fuelCardRepository,
        IRepository<FuelRefillMedia> fuelRefillMediaRepository,
        IRepository<Media> mediaRepository,
        IRepository<FuelCardTransaction> transactionRepository,
        IUnifiedMediaService unifiedMediaService,
        ITruckService truckService)
    {
        _fuelRefillRepository = fuelRefillRepository;
        _truckRepository = truckRepository;
        _fuelCardRepository = fuelCardRepository;
        _fuelRefillMediaRepository = fuelRefillMediaRepository;
        _mediaRepository = mediaRepository;
        _transactionRepository = transactionRepository;
        _unifiedMediaService = unifiedMediaService;
        _truckService = truckService;
    }

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

        try
        {
            // Validate PreviousOdo is required
            if (model.PreviousOdo <= 0)
            {
                result.Message = "Số ODO trước đó là bắt buộc";
                return result;
            }

            // Validate CurrentOdo > PreviousOdo
            if (model.CurrentOdo <= model.PreviousOdo)
            {
                result.Message = $"ODO hiện tại ({model.CurrentOdo}) phải lớn hơn ODO trước đó ({model.PreviousOdo})";
                return result;
            }

            // Validate required media types for Create or Update with media changes
            if (model.Id == 0 || (model.ExistingMediaIds != null && model.ExistingMediaIds.Count > 0))
            {
                // Determine which media types are present
                List<TruckActivityMediaType> presentMediaTypes;

                if (model.Id == 0)
                {
                    // For Create: check Files and MediaTypes
                    if (model.Files == null || model.Files.Count == 0 || model.MediaTypes == null || model.MediaTypes.Count == 0)
                    {
                        result.Message = "Phải upload đủ 4 loại hình ảnh: ODO trước, ODO sau, cây dầu, hóa đơn";
                        return result;
                    }
                    presentMediaTypes = model.MediaTypes;
                }
                else
                {
                    // For Update with media changes: combine existing and new media types
                    presentMediaTypes = new List<TruckActivityMediaType>();

                    // Get existing media types from database
                    var existingMedia = await _fuelRefillMediaRepository.Query()
                        .Where(x => x.FuelRefillId == model.Id && !x.IsDeleted && model.ExistingMediaIds.Contains(x.Id))
                        .Select(x => x.MediaType)
                        .ToListAsync();

                    presentMediaTypes.AddRange(existingMedia);

                    // Add new media types from Files
                    if (model.MediaTypes != null)
                    {
                        presentMediaTypes.AddRange(model.MediaTypes);
                    }
                }

                // Check for all 4 required media types
                var requiredMediaTypes = new[]
                {
                    TruckActivityMediaType.OdoBeforePhoto,
                    TruckActivityMediaType.OdoAfterPhoto,
                    TruckActivityMediaType.FuelPumpPhoto,
                    TruckActivityMediaType.FuelReceiptPhoto
                };

                var missingMediaTypes = requiredMediaTypes.Where(r => !presentMediaTypes.Contains(r)).ToList();

                if (missingMediaTypes.Any())
                {
                    var missingNames = string.Join(", ", missingMediaTypes.Select(m => m.GetDescription()));
                    result.Message = $"Thiếu các loại hình ảnh bắt buộc: {missingNames}";
                    return result;
                }
            }

            if (model.Id > 0)
            {
                // Cập nhật
                return await Update(model, currentUser);
            }
            else
            {
                // Thêm mới
                return await Create(model, currentUser);
            }
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

    private async Task<BaseResult> Create(FuelRefillModel model, CurrentUser currentUser)
    {
        var result = new BaseResult();

        try
        {
            // 1. Validate truck
            var truck = await _truckRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == model.TruckId && !x.IsDeleted);

            if (truck == null)
            {
                result.Message = "Không tìm thấy xe tải";
                return result;
            }

            // 2. Determine driver ID (use model.DriverId if provided, otherwise current user)
            int driverId = model.DriverId ?? currentUser.UserId;

            // 3. Validate images
            if (model.Files == null || model.Files.Count == 0)
            {
                result.Message = "Phải upload ít nhất 1 hình ảnh";
                return result;
            }

            if (model.Files.Count != model.MediaTypes.Count)
            {
                result.Message = "Số lượng hình ảnh và loại hình ảnh không khớp";
                return result;
            }

            // 4. Calculate values
            int distanceKm = model.CurrentOdo - model.PreviousOdo;
            decimal actualLiters = model.Amount / model.UnitPrice;
            decimal fuelQuotaPer100Km = truck.FuelQuotaPer100Km;
            decimal quotaLiters = (distanceKm * fuelQuotaPer100Km) / 100;
            decimal differenceLiters = quotaLiters - actualLiters;

            // 5. Create FuelRefill
            var fuelRefill = new FuelRefill
            {
                TruckId = model.TruckId,
                DriverId = driverId,
                FuelCardId = model.FuelCardId,
                PreviousOdo = model.PreviousOdo,
                CurrentOdo = model.CurrentOdo,
                DistanceKm = distanceKm,
                Amount = model.Amount,
                UnitPrice = model.UnitPrice,
                ActualLiters = actualLiters,
                FuelQuotaPer100Km = fuelQuotaPer100Km,
                QuotaLiters = quotaLiters,
                DifferenceLiters = differenceLiters,
                PaymentMethod = model.PaymentMethod,
                StationName = model.StationName,
                StationAddress = model.StationAddress,
                RefillTime = model.RefillTime.ToLocalTime(),
                Notes = model.Notes,
                IsDeleted = false
            };

            // Update common fields (CreatedTime, CreatedBy, UpdatedTime, UpdatedBy)
            fuelRefill = fuelRefill.UpdateCommonInt(currentUser.UserId, currentUser.UserName);

            await _fuelRefillRepository.InsertAsync(fuelRefill);

            // 6. Reconcile with FuelCardTransaction if provided
            if (model.FuelCardTransactionId.HasValue)
            {
                var transaction = await _transactionRepository.Query()
                    .FirstOrDefaultAsync(x => x.Id == model.FuelCardTransactionId.Value && !x.IsDeleted);

                if (transaction != null)
                {
                    // Validate: transaction must belong to the same fuel card
                    if (model.FuelCardId.HasValue && transaction.FuelCardId != model.FuelCardId.Value)
                    {
                        result.Message = "Giao dịch không thuộc thẻ xăng dầu đã chọn";
                        return result;
                    }

                    // Validate: transaction must not be already reconciled
                    if (transaction.IsReconciled)
                    {
                        result.Message = "Giao dịch đã được đối soát với lần đổ dầu khác";
                        return result;
                    }

                    // Update FuelRefill
                    fuelRefill.FuelCardTransactionId = model.FuelCardTransactionId.Value;
                    await _fuelRefillRepository.UpdateAsync(fuelRefill);

                    // Update FuelCardTransaction (bidirectional)
                    transaction.FuelRefillId = fuelRefill.Id;
                    transaction.IsReconciled = true;
                    transaction.UpdatedTime = DateTimeOffset.Now;
                    transaction.UpdatedBy = currentUser.UserId;
                    transaction.UpdatedByUserName = currentUser.UserName;
                    await _transactionRepository.UpdateAsync(transaction);
                }
            }

            // 7. Upload media files and link to FuelRefill
            for (int i = 0; i < model.Files.Count; i++)
            {
                var file = model.Files[i];
                var mediaType = model.MediaTypes[i];

                // Process image
                var processResult = await _unifiedMediaService.ProcessImageAsync(file, ImageType.TruckActivity);

                if (processResult.Result == Result.Success)
                {
                    // Create Media entity
                    var media = new Media
                    {
                        Id = Guid.NewGuid(),
                        SystemPath = processResult.SystemPath,
                        AltText = $"Ảnh đổ dầu - {mediaType.GetDescription()}",
                        Caption = $"Ảnh đổ dầu - {mediaType.GetDescription()}",
                        DisplayOrder = i,
                        IsDeleted = false
                    };
                    media = media.UpdateCommonGuid(currentUser.UserId, currentUser.UserName);

                    await _mediaRepository.InsertAsync(media);

                    // Save FuelRefillMedia
                    var fuelRefillMedia = new FuelRefillMedia
                    {
                        FuelRefillId = fuelRefill.Id,
                        MediaId = media.Id,
                        MediaType = mediaType,
                        DisplayOrder = i + 1,
                        IsDeleted = false
                    };
                    fuelRefillMedia = fuelRefillMedia.UpdateCommonInt(currentUser.UserId, currentUser.UserName);

                    await _fuelRefillMediaRepository.InsertAsync(fuelRefillMedia);
                }
            }



            // 7. Update LastRefillOdo in Truck
            await _truckService.UpdateLastRefillOdo(model.TruckId, model.CurrentOdo);

            result.Result = Result.Success;
            result.Message = $"Đổ dầu thành công. Chênh lệch: {differenceLiters:F2} lít {(differenceLiters >= 0 ? "(được hưởng)" : "(phải bù)")}";
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

    private async Task<BaseResult> Update(FuelRefillModel model, CurrentUser currentUser)
    {
        var result = new BaseResult { Result = Result.Failed };

        try
        {
            // 1. Validate và lấy bản ghi FuelRefill
            var fuelRefill = await _fuelRefillRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == model.Id && !x.IsDeleted);

            if (fuelRefill == null)
            {
                result.Message = "Không tìm thấy bản ghi đổ dầu";
                return result;
            }

            // 2. Validate Truck exists
            var truck = await _truckRepository.GetByIdAsync(model.TruckId);
            if (truck == null)
            {
                result.Message = "Không tìm thấy xe tải";
                return result;
            }

            // 3. Validate FuelCard if provided
            if (model.FuelCardId.HasValue)
            {
                var fuelCard = await _fuelCardRepository.GetByIdAsync(model.FuelCardId.Value);
                if (fuelCard == null)
                {
                    result.Message = "Không tìm thấy thẻ xăng dầu";
                    return result;
                }
            }

            // 4. Validate images if provided
            if (model.Files != null && model.Files.Count > 0)
            {
                if (model.Files.Count != model.MediaTypes.Count)
                {
                    result.Message = "Số lượng hình ảnh và loại hình ảnh không khớp";
                    return result;
                }
            }

            // 5. Determine driver ID
            int driverId = model.DriverId ?? currentUser.UserId;

            // 6. Calculate values
            int distanceKm = model.CurrentOdo - model.PreviousOdo;
            decimal actualLiters = model.Amount / model.UnitPrice;
            decimal fuelQuotaPer100Km = truck.FuelQuotaPer100Km;
            decimal quotaLiters = distanceKm > 0 ? (distanceKm * fuelQuotaPer100Km / 100) : 0;
            decimal differenceLiters = quotaLiters - actualLiters;

            // 7. Update FuelRefill entity
            fuelRefill.TruckId = model.TruckId;
            fuelRefill.FuelCardId = model.FuelCardId;
            fuelRefill.DriverId = driverId;
            fuelRefill.PreviousOdo = model.PreviousOdo;
            fuelRefill.CurrentOdo = model.CurrentOdo;
            fuelRefill.DistanceKm = distanceKm;
            fuelRefill.Amount = model.Amount;
            fuelRefill.UnitPrice = model.UnitPrice;
            fuelRefill.ActualLiters = actualLiters;
            fuelRefill.FuelQuotaPer100Km = fuelQuotaPer100Km;
            fuelRefill.QuotaLiters = quotaLiters;
            fuelRefill.DifferenceLiters = differenceLiters;
            fuelRefill.StationName = model.StationName;
            fuelRefill.StationAddress = model.StationAddress;
            fuelRefill.RefillTime = model.RefillTime.ToLocalTime();
            fuelRefill.Notes = model.Notes;
            fuelRefill.PaymentMethod = model.PaymentMethod;

            // Update common fields (UpdatedTime, UpdatedBy)
            fuelRefill = fuelRefill.UpdateCommonInt(currentUser.UserId, currentUser.UserName);

            await _fuelRefillRepository.UpdateAsync(fuelRefill);

            // 8. Handle FuelCardTransaction reconciliation changes
            await HandleTransactionReconciliationAsync(
                fuelRefill,
                model.FuelCardTransactionId,
                model.FuelCardId,
                currentUser);

            // 9. Update media with selective update strategy (only if ExistingMediaIds is provided)
            if (model.ExistingMediaIds != null && model.ExistingMediaIds.Count > 0)
            {
                // Get current media items
                var currentMediaItems = await _fuelRefillMediaRepository.Query()
                    .Where(x => x.FuelRefillId == model.Id && !x.IsDeleted)
                    .OrderBy(x => x.DisplayOrder)
                    .ToListAsync();

                var currentMediaIds = currentMediaItems.Select(x => x.Id).ToList();
                var existingMediaIds = model.ExistingMediaIds;

                // 8.1. Soft delete media that are no longer needed
                var mediaIdsToDelete = currentMediaIds.Except(existingMediaIds).ToList();
                if (mediaIdsToDelete.Any())
                {
                    var mediaToDelete = currentMediaItems.Where(x => mediaIdsToDelete.Contains(x.Id)).ToList();
                    foreach (var media in mediaToDelete)
                    {
                        media.IsDeleted = true;
                        media.UpdatedBy = currentUser.UserId;
                        media.UpdatedByUserName = currentUser.UserName;
                        media.UpdatedTime = DateTimeOffset.Now;
                        await _fuelRefillMediaRepository.UpdateAsync(media);
                    }
                }

                // 8.2. Upload new media files (where ExistingMediaIds[i] == 0)
                if (model.Files != null && model.Files.Count > 0)
                {
                    for (int i = 0; i < model.Files.Count; i++)
                    {
                        // Check if this position needs a new upload (ID == 0)
                        if (i < existingMediaIds.Count && existingMediaIds[i] == 0)
                        {
                            var file = model.Files[i];
                            var mediaType = model.MediaTypes[i];

                            // Process image
                            var processResult = await _unifiedMediaService.ProcessImageAsync(file, ImageType.TruckActivity);

                            if (processResult.Result == Result.Success)
                            {
                                // Create Media entity
                                var media = new Media
                                {
                                    Id = Guid.NewGuid(),
                                    SystemPath = processResult.SystemPath,
                                    AltText = $"Ảnh đổ dầu - {mediaType.GetDescription()}",
                                    Caption = $"Ảnh đổ dầu - {mediaType.GetDescription()}",
                                    DisplayOrder = i,
                                    IsDeleted = false
                                };
                                media = media.UpdateCommonGuid(currentUser.UserId, currentUser.UserName);

                                await _mediaRepository.InsertAsync(media);

                                // Save FuelRefillMedia
                                var fuelRefillMedia = new FuelRefillMedia
                                {
                                    FuelRefillId = fuelRefill.Id,
                                    MediaId = media.Id,
                                    MediaType = mediaType,
                                    DisplayOrder = i + 1,
                                    IsDeleted = false
                                };
                                fuelRefillMedia = fuelRefillMedia.UpdateCommonInt(currentUser.UserId, currentUser.UserName);

                                await _fuelRefillMediaRepository.InsertAsync(fuelRefillMedia);
                            }
                        }
                    }
                }

                // 8.3. Update DisplayOrder for kept media items
                if (existingMediaIds.Any())
                {
                    for (int i = 0; i < existingMediaIds.Count; i++)
                    {
                        var mediaId = existingMediaIds[i];
                        if (mediaId > 0)
                        {
                            var mediaItem = currentMediaItems.FirstOrDefault(x => x.Id == mediaId);
                            if (mediaItem != null && mediaItem.DisplayOrder != i + 1)
                            {
                                mediaItem.DisplayOrder = i + 1;
                                mediaItem.UpdatedBy = currentUser.UserId;
                                mediaItem.UpdatedByUserName = currentUser.UserName;
                                mediaItem.UpdatedTime = DateTimeOffset.Now;
                                await _fuelRefillMediaRepository.UpdateAsync(mediaItem);
                            }
                        }
                    }
                }
            }

            // 9. Update LastRefillOdo in Truck if this is the latest refill
            var latestRefill = await _fuelRefillRepository.Query()
                .Where(x => x.TruckId == model.TruckId && !x.IsDeleted)
                .OrderByDescending(x => x.RefillTime)
                .ThenByDescending(x => x.Id)
                .FirstOrDefaultAsync();

            if (latestRefill != null && latestRefill.Id == model.Id)
            {
                await _truckService.UpdateLastRefillOdo(model.TruckId, model.CurrentOdo);
            }

            result.Result = Result.Success;
            result.Message = $"Cập nhật thông tin đổ dầu thành công. Chênh lệch: {differenceLiters:F2} lít {(differenceLiters >= 0 ? "(được hưởng)" : "(phải bù)}")}";
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

    [Obsolete("Sử dụng CreateOrUpdate thay thế")]
    public async Task<BaseResult> RefillFuelAsync(FuelRefillModel model, CurrentUser currentUser)
    {
        return await CreateOrUpdate(model, currentUser);
    }

    /// <summary>
    /// Đổ dầu cho lái xe trên app mobile.
    /// Tự động xác định xe, lái xe, PreviousOdo.
    /// </summary>
    public async Task<BaseResult> DriverFuelRefill(DriverFuelRefillModel model, CurrentUser currentUser)
    {
        var result = new BaseResult();

        try
        {
            // 1. Lấy xe hiện tại của lái xe (dựa trên CurrentDriverId)
            var truck = await _truckRepository.Query()
                .FirstOrDefaultAsync(t => t.CurrentDriverId == currentUser.UserId && !t.IsDeleted);

            if (truck == null)
            {
                result.Result = Result.Failed;
                result.Message = "Bạn chưa nhận xe nào. Vui lòng nhận xe trước khi đổ dầu.";
                return result;
            }

            // 2. Lấy PreviousOdo từ LastRefillOdo (hoặc 0 nếu chưa có)
            int previousOdo = truck.LastRefillOdo ?? 0;

            // 3. Validate CurrentOdo > PreviousOdo
            if (previousOdo > 0 && model.CurrentOdo <= previousOdo)
            {
                result.Result = Result.Failed;
                result.Message = $"ODO hiện tại ({model.CurrentOdo}) phải lớn hơn ODO lần đổ trước ({previousOdo})";
                return result;
            }

            // 4. Validate FuelCard nếu có
            if (model.FuelCardId.HasValue)
            {
                var fuelCard = await _fuelCardRepository.Query()
                    .FirstOrDefaultAsync(x => x.Id == model.FuelCardId.Value && !x.IsDeleted);

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

            // 5. Chuyển đổi sang FuelRefillModel và gọi logic Create có sẵn
            var fuelRefillModel = new FuelRefillModel
            {
                TruckId = truck.Id,
                DriverId = currentUser.UserId,
                FuelCardId = model.FuelCardId,
                FuelCardTransactionId = null, // Lái xe không chọn giao dịch
                CurrentOdo = model.CurrentOdo,
                PreviousOdo = previousOdo,
                Amount = model.Amount,
                UnitPrice = model.UnitPrice,
                PaymentMethod = model.PaymentMethod,
                StationName = model.StationName,
                StationAddress = model.StationAddress,
                RefillTime = model.RefillTime,
                Notes = model.Notes,
                Files = model.Files,
                MediaTypes = model.MediaTypes
            };

            result = await Create(fuelRefillModel, currentUser);
        }
        catch (Exception ex)
        {
            result.Result = Result.SystemError;
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

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

        var query = _fuelRefillRepository.Query()
            .Include(x => x.Truck)
            .Include(x => x.Driver)
            .Include(x => x.FuelCard)
            .Include(x => x.FuelRefillMedias).ThenInclude(m => m.Media)
            .Where(x => !x.IsDeleted);

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

            // Filter by TruckId
            if (search.TruckId != null)
            {
                int truckId = search.TruckId;
                if (truckId > 0)
                {
                    query = query.Where(x => x.TruckId == truckId);
                }
            }

            // Filter by Keyword
            if (search.Keyword != null)
            {
                string keyword = search.Keyword.ToString().ToLower().Trim();
                if (!string.IsNullOrEmpty(keyword))
                {
                    query = query.Where(x =>
                        x.Truck.LicensePlate.ToLower().Contains(keyword) ||
                        x.Driver.UserName.ToLower().Contains(keyword) ||
                        x.StationName.ToLower().Contains(keyword));
                }
            }

            // Filter by RefillTime range
            if (search.RefillStart != null && search.RefillEnd != null)
            {
                DateTimeOffset start = search.RefillStart;
                DateTimeOffset end = search.RefillEnd;
                DateTimeOffset startParam = start.ToLocalTime().StartOfDay();
                DateTimeOffset endParam = end.ToLocalTime().EndOfDay();
                query = query.Where(x => x.RefillTime >= startParam && x.RefillTime <= endParam);
            }
        }

        // Sorting
        if (!string.IsNullOrWhiteSpace(param.Sort?.Predicate))
        {
            query = param.Sort.Predicate.ToLower() switch
            {
                "refilltime" => param.Sort.Reverse ? query.OrderByDescending(x => x.RefillTime) : query.OrderBy(x => x.RefillTime),
                "differenceliters" => param.Sort.Reverse ? query.OrderByDescending(x => x.DifferenceLiters) : query.OrderBy(x => x.DifferenceLiters),
                _ => query.OrderByDescending(x => x.RefillTime)
            };
        }
        else
        {
            param.Sort = new Sort() { Predicate = "RefillTime", Reverse = true };
        }

        // Use ToSmartTableResultAsync with AutoMapper pattern
        var result = await query.ToSmartTableResultAsync(param, x => x.ToItem());

        // Convert SystemPath to display URL
        if (result.Items != null)
        {
            foreach (var item in result.Items)
            {
                if (item.MediaItems != null)
                {
                    foreach (var mediaItem in item.MediaItems)
                    {
                        if (!string.IsNullOrEmpty(mediaItem.MediaUrl))
                        {
                            mediaItem.MediaUrl = await _unifiedMediaService.GetUrlBySystemPathAsync(mediaItem.MediaUrl);
                        }
                    }
                }
            }
        }

        return result;
    }

    public async Task<FuelRefillItem?> GetByIdAsync(int id)
    {
        var entity = await _fuelRefillRepository.Query()
            .Include(x => x.Truck)
            .Include(x => x.Driver)
            .Include(x => x.FuelCard)
            .FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);

        if (entity == null) return null;

        // Get media items from FuelRefillMedia
        var mediaItems = await _fuelRefillMediaRepository.Query()
            .Include(x => x.Media)
            .Where(x => x.FuelRefillId == id && !x.IsDeleted)
            .OrderBy(x => x.DisplayOrder)
            .Select(x => new Infrastructures.DTO.Items.Trucks.TruckActivityMediaItem
            {
                Id = x.Id,
                TruckActivityId = 0, // Not used anymore
                MediaId = x.MediaId,
                MediaUrl = _unifiedMediaService.GetUrlBySystemPathAsync(x.Media.SystemPath).Result,
                AltText = x.Media.AltText,
                Caption = x.Media.Caption,
                MediaType = x.MediaType,
                DisplayOrder = x.DisplayOrder
            })
            .ToListAsync();

        // Use ToItem() extension method for mapping
        var result = entity.ToItem();
        result.MediaItems = mediaItems;

        return result;
    }

    public async Task<List<FuelRefillItem>> GetByTruckAsync(int truckId)
    {
        return await _fuelRefillRepository.Query()
            .Include(x => x.Truck)
            .Include(x => x.Driver)
            .Include(x => x.FuelCard)
            .Where(x => x.TruckId == truckId && !x.IsDeleted)
            .OrderByDescending(x => x.RefillTime)
            .Select(x => new FuelRefillItem
            {
                Id = x.Id,
                TruckActivityId = 0, // Not used anymore
                TruckId = x.TruckId,
                TruckLicensePlate = x.Truck.LicensePlate,
                DriverId = x.DriverId,
                DriverName = x.Driver.UserName,
                FuelCardId = x.FuelCardId,
                FuelCardNumber = x.FuelCard != null ? x.FuelCard.CardNumber : null,
                PreviousOdo = x.PreviousOdo,
                CurrentOdo = x.CurrentOdo,
                DistanceKm = x.DistanceKm,
                Amount = x.Amount,
                UnitPrice = x.UnitPrice,
                ActualLiters = x.ActualLiters,
                FuelQuotaPer100Km = x.FuelQuotaPer100Km,
                QuotaLiters = x.QuotaLiters,
                DifferenceLiters = x.DifferenceLiters,
                PaymentMethod = x.PaymentMethod,
                StationName = x.StationName,
                RefillTime = x.RefillTime,
                Notes = x.Notes
            })
            .ToListAsync();
    }

    public async Task<List<FuelRefillItem>> GetByDriverAsync(int driverId)
    {
        return await _fuelRefillRepository.Query()
            .Include(x => x.Truck)
            .Include(x => x.Driver)
            .Include(x => x.FuelCard)
            .Include(x => x.FuelRefillMedias).ThenInclude(m => m.Media)
            .Where(x => x.DriverId == driverId && !x.IsDeleted)
            .OrderByDescending(x => x.RefillTime)
            .Select(x => new FuelRefillItem
            {
                Id = x.Id,
                TruckActivityId = 0, // Not used anymore
                TruckId = x.TruckId,
                TruckLicensePlate = x.Truck.LicensePlate,
                DriverId = x.DriverId,
                DriverName = x.Driver.UserName,
                FuelCardId = x.FuelCardId,
                FuelCardNumber = x.FuelCard != null ? x.FuelCard.CardNumber : null,
                PreviousOdo = x.PreviousOdo,
                CurrentOdo = x.CurrentOdo,
                DistanceKm = x.DistanceKm,
                Amount = x.Amount,
                UnitPrice = x.UnitPrice,
                ActualLiters = x.ActualLiters,
                FuelQuotaPer100Km = x.FuelQuotaPer100Km,
                QuotaLiters = x.QuotaLiters,
                DifferenceLiters = x.DifferenceLiters,
                PaymentMethod = x.PaymentMethod,
                StationName = x.StationName,
                RefillTime = x.RefillTime,
                Notes = x.Notes
            })
            .ToListAsync();
    }

    /// <summary>
    /// Tìm kiếm lịch sử đổ dầu theo lái xe (có phân trang, lọc ngày, từ khóa)
    /// Lái xe có thể lái nhiều xe khác nhau nên lọc theo DriverId
    /// </summary>
    public async Task<SmartTableResult<FuelRefillItem>> SearchByDriverAsync(int driverId, SmartTableParam param)
    {
        param ??= new SmartTableParam();

        var query = _fuelRefillRepository.Query()
            .Include(x => x.Truck)
            .Include(x => x.Driver)
            .Include(x => x.FuelCard)
            .Include(x => x.FuelRefillMedias).ThenInclude(m => m.Media)
            .Where(x => x.DriverId == driverId && !x.IsDeleted);

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

            // Filter by RefillTime range
            if (search.RefillStart != null && search.RefillEnd != null)
            {
                DateTimeOffset start = search.RefillStart;
                DateTimeOffset end = search.RefillEnd;
                DateTimeOffset startParam = start.ToLocalTime().StartOfDay();
                DateTimeOffset endParam = end.ToLocalTime().EndOfDay();
                query = query.Where(x => x.RefillTime >= startParam && x.RefillTime <= endParam);
            }

            // Filter by Keyword (biển số xe hoặc tên cây xăng)
            if (search.Keyword != null)
            {
                string keyword = search.Keyword.ToString().ToLower().Trim();
                if (!string.IsNullOrEmpty(keyword))
                {
                    query = query.Where(x =>
                        x.Truck.LicensePlate.ToLower().Contains(keyword) ||
                        x.StationName.ToLower().Contains(keyword));
                }
            }
        }

        // Default sort: RefillTime giảm dần (mới nhất trước)
        param.Sort = new Sort() { Predicate = "RefillTime", Reverse = true };

        // Use ToSmartTableResultAsync with AutoMapper pattern
        var result = await query.ToSmartTableResultAsync(param, x => x.ToItem());

        // Convert SystemPath to display URL
        if (result.Items != null)
        {
            foreach (var item in result.Items)
            {
                if (item.MediaItems != null)
                {
                    foreach (var mediaItem in item.MediaItems)
                    {
                        if (!string.IsNullOrEmpty(mediaItem.MediaUrl))
                        {
                            mediaItem.MediaUrl = await _unifiedMediaService.GetUrlBySystemPathAsync(mediaItem.MediaUrl);
                        }
                    }
                }
            }
        }

        return result;
    }

    /// <summary>
    /// Cập nhật thông tin đổ dầu
    /// </summary>
    public async Task<BaseResult> UpdateRefillAsync(FuelRefillUpdateModel model, CurrentUser currentUser)
    {
        var result = new BaseResult { Result = Result.Failed };

        try
        {
            // 1. Validate và lấy bản ghi FuelRefill
            var fuelRefill = await _fuelRefillRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == model.Id && !x.IsDeleted);

            if (fuelRefill == null)
            {
                result.Message = "Không tìm thấy bản ghi đổ dầu";
                return result;
            }

            // 2. Validate Truck exists
            var truck = await _truckRepository.GetByIdAsync(model.TruckId);
            if (truck == null)
            {
                result.Message = "Không tìm thấy xe tải";
                return result;
            }

            // 3. Validate FuelCard if provided
            if (model.FuelCardId.HasValue)
            {
                var fuelCard = await _fuelCardRepository.GetByIdAsync(model.FuelCardId.Value);
                if (fuelCard == null)
                {
                    result.Message = "Không tìm thấy thẻ xăng dầu";
                    return result;
                }
            }

            // 4. Use PreviousOdo from model
            int previousOdo = model.PreviousOdo;

            // 5. Calculate values
            int distanceKm = model.CurrentOdo - previousOdo;
            if (distanceKm < 0)
            {
                result.Message = $"ODO hiện tại ({model.CurrentOdo}) không được nhỏ hơn ODO trước đó ({previousOdo})";
                return result;
            }

            decimal fuelQuotaPer100Km = truck.FuelQuotaPer100Km;
            decimal quotaLiters = distanceKm > 0 ? (distanceKm * fuelQuotaPer100Km / 100) : 0;
            decimal differenceLiters = quotaLiters - model.ActualLiters;

            // 6. Update FuelRefill entity
            fuelRefill.TruckId = model.TruckId;
            fuelRefill.FuelCardId = model.FuelCardId;
            fuelRefill.DriverId = model.DriverId;
            fuelRefill.PreviousOdo = previousOdo;
            fuelRefill.CurrentOdo = model.CurrentOdo;
            fuelRefill.DistanceKm = distanceKm;
            fuelRefill.Amount = model.Amount;
            fuelRefill.UnitPrice = model.UnitPrice;
            fuelRefill.ActualLiters = model.ActualLiters;
            fuelRefill.FuelQuotaPer100Km = fuelQuotaPer100Km;
            fuelRefill.QuotaLiters = quotaLiters;
            fuelRefill.DifferenceLiters = differenceLiters;
            fuelRefill.StationName = model.StationName;
            fuelRefill.StationAddress = model.StationAddress;
            fuelRefill.RefillTime = model.RefillTime.ToLocalTime();
            fuelRefill.Notes = model.Notes;

            await _fuelRefillRepository.UpdateAsync(fuelRefill);

            // 7. Update LastRefillOdo in Truck if this is the latest refill
            var latestRefill = await _fuelRefillRepository.Query()
                .Where(x => x.TruckId == model.TruckId && !x.IsDeleted)
                .OrderByDescending(x => x.RefillTime)
                .ThenByDescending(x => x.Id)
                .FirstOrDefaultAsync();

            if (latestRefill != null && latestRefill.Id == model.Id)
            {
                await _truckService.UpdateLastRefillOdo(model.TruckId, model.CurrentOdo);
            }

            result.Result = Result.Success;
            result.Message = "Cập nhật thông tin đổ dầu thành công";
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

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

        try
        {
            // 1. Validate và lấy bản ghi FuelRefill
            var fuelRefill = await _fuelRefillRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted);

            if (fuelRefill == null)
            {
                result.Message = "Không tìm thấy bản ghi đổ dầu";
                return result;
            }

            // 2. Xóa media liên quan
            var mediaItems = await _fuelRefillMediaRepository.Query()
                .Where(x => x.FuelRefillId == id && !x.IsDeleted)
                .ToListAsync();

            foreach (var mediaItem in mediaItems)
            {
                mediaItem.IsDeleted = true;
                mediaItem.UpdatedBy = currentUser.UserId;
                mediaItem.UpdatedByUserName = currentUser.UserName;
                mediaItem.UpdatedTime = DateTimeOffset.Now;
                await _fuelRefillMediaRepository.UpdateAsync(mediaItem);
            }

            // 3. Soft delete FuelRefill
            fuelRefill.IsDeleted = true;
            fuelRefill.UpdatedBy = currentUser.UserId;
            fuelRefill.UpdatedByUserName = currentUser.UserName;
            fuelRefill.UpdatedTime = DateTimeOffset.Now;
            await _fuelRefillRepository.UpdateAsync(fuelRefill);

            result.Result = Result.Success;
            result.Message = "Xóa bản ghi đổ dầu thành công";
        }
        catch (Exception ex)
        {
            result.Message = $"Lỗi: {ex.Message}";
        }

        return result;
    }

    /// <summary>
    /// Handle transaction reconciliation changes when creating or updating fuel refill
    /// </summary>
    private async Task HandleTransactionReconciliationAsync(
        FuelRefill fuelRefill,
        Guid? newTransactionId,
        int? fuelCardId,
        CurrentUser currentUser)
    {
        var oldTransactionId = fuelRefill.FuelCardTransactionId;

        // Case 1: No change
        if (oldTransactionId == newTransactionId)
            return;

        // Case 2: Remove old reconciliation
        if (oldTransactionId.HasValue)
        {
            var oldTransaction = await _transactionRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == oldTransactionId.Value && !x.IsDeleted);

            if (oldTransaction != null)
            {
                oldTransaction.FuelRefillId = null;
                oldTransaction.IsReconciled = false;
                oldTransaction.UpdatedTime = DateTimeOffset.Now;
                oldTransaction.UpdatedBy = currentUser.UserId;
                oldTransaction.UpdatedByUserName = currentUser.UserName;
                await _transactionRepository.UpdateAsync(oldTransaction);
            }
        }

        // Case 3: Add new reconciliation
        if (newTransactionId.HasValue)
        {
            var newTransaction = await _transactionRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == newTransactionId.Value && !x.IsDeleted);

            if (newTransaction != null)
            {
                // Validate: transaction must belong to the same fuel card
                if (fuelCardId.HasValue && newTransaction.FuelCardId != fuelCardId.Value)
                {
                    throw new InvalidOperationException("Giao dịch không thuộc thẻ xăng dầu đã chọn");
                }

                // Validate: transaction must not be already reconciled with another refill
                if (newTransaction.IsReconciled && newTransaction.FuelRefillId != fuelRefill.Id)
                {
                    throw new InvalidOperationException("Giao dịch đã được đối soát với lần đổ dầu khác");
                }

                // Update FuelRefill
                fuelRefill.FuelCardTransactionId = newTransactionId.Value;
                await _fuelRefillRepository.UpdateAsync(fuelRefill);

                // Update FuelCardTransaction
                newTransaction.FuelRefillId = fuelRefill.Id;
                newTransaction.IsReconciled = true;
                newTransaction.UpdatedTime = DateTimeOffset.Now;
                newTransaction.UpdatedBy = currentUser.UserId;
                newTransaction.UpdatedByUserName = currentUser.UserName;
                await _transactionRepository.UpdateAsync(newTransaction);
            }
        }
        else
        {
            // Case 4: Remove reconciliation (set to null)
            fuelRefill.FuelCardTransactionId = null;
            await _fuelRefillRepository.UpdateAsync(fuelRefill);
        }
    }
}
