using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Enums;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.DriverApp;
using Ladaer.BackEnd.Infrastructures.DTO.Models.DriverApp;
using Ladaer.BackEnd.Infrastructures.Services.Categories;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.DriverApp
{
    /// <summary>
    /// Interface cho dịch vụ quản lý tài chính của lái xe
    /// </summary>
    public interface IDriverFinService
    {
        /// <summary>
        /// Lấy thông tin tài chính của lái xe
        /// </summary>
        /// <param name="userId">ID của lái xe</param>
        /// <returns>Thông tin tài chính của lái xe</returns>
        Task<DriverFinModel> GetDriverFinancialInfo(int userId);

        /// <summary>
        /// Tìm kiếm danh sách đơn hàng tài chính của lái xe có phân trang
        /// </summary>
        /// <param name="param">Tham số tìm kiếm và phân trang</param>
        /// <param name="userId">ID của lái xe</param>
        /// <returns>Kết quả tìm kiếm có phân trang</returns>
        Task<SmartTableResult<DriverFinOrderItem>> Search(SmartTableParam param, int userId);
    }

    /// <summary>
    /// Dịch vụ quản lý tài chính của lái xe
    /// </summary>
    public class DriverFinService : IDriverFinService
    {
        private readonly IRepository<OrderFin> _orderFinRepository;
        private readonly IRepository<Order> _orderRepository;
        private readonly ILocationService _locationService;

        public DriverFinService(
            IRepository<OrderFin> orderFinRepository,
            IRepository<Order> orderRepository,
            ILocationService locationService)
        {
            _orderFinRepository = orderFinRepository;
            _orderRepository = orderRepository;
            _locationService = locationService;
        }

        /// <summary>
        /// Lấy thông tin tài chính của lái xe
        /// </summary>
        /// <param name="userId">ID của lái xe</param>
        /// <returns>Thông tin tài chính của lái xe</returns>
        public async Task<DriverFinModel> GetDriverFinancialInfo(int userId)
        {
            var result = new DriverFinModel();

            try
            {
                // Lấy tất cả OrderFin mà lái xe đang cầm tiền
                var orderFins = await _orderFinRepository.Query()
                    .Where(of => of.SourceFeeCashierId == userId ||
                                of.DestFeeCashierId == userId ||
                                of.CodCashierId == userId)
                    .ToListAsync();

                // Tính tổng số tiền theo từng loại
                result.TotalSourceFee = orderFins
                    .Where(of => of.SourceFeeCashierId == userId)
                    .Sum(of => of.SourceFee);

                result.TotalDestFee = orderFins
                    .Where(of => of.DestFeeCashierId == userId)
                    .Sum(of => of.DestFee);

                result.TotalCollectAmount = orderFins
                    .Where(of => of.CodCashierId == userId)
                    .Sum(of => of.CollectAmount);

                // Lấy 10 đơn gần đây nhất mà lái xe đang cầm tiền
                var orderIds = orderFins.Select(of => of.Id).ToList();

                var orders = await _orderRepository.Query()
                    .Include(o => o.OrderFin)
                    .Include(o => o.Customer)
                    .Include(o => o.OrderOps)
                    .Include(o => o.Addresses)
                    .Where(o => orderIds.Contains(o.Id))
                    .OrderByDescending(o => o.CreatedTime)
                    .Take(10)
                    .ToListAsync();

                var recentOrders = orders.Select(o => o.ToDriverFinOrderItem(userId)).ToList();

                // Enrich địa chỉ với tên phường/quận/tỉnh
                await EnrichAddressesAsync(recentOrders);

                result.RecentOrders = recentOrders;
            }
            catch (Exception)
            {
                // Log error nhưng không làm fail
                // Trả về model rỗng nếu có lỗi
                result = new DriverFinModel();
            }

            return result;
        }

        /// <summary>
        /// Tìm kiếm danh sách đơn hàng tài chính của lái xe có phân trang
        /// Bao gồm cả đơn hàng mà lái xe đã thu tiền nhưng đã nộp lại
        /// </summary>
        /// <param name="param">Tham số tìm kiếm và phân trang</param>
        /// <param name="userId">ID của lái xe</param>
        /// <returns>Kết quả tìm kiếm có phân trang</returns>
        public async Task<SmartTableResult<DriverFinOrderItem>> Search(SmartTableParam param, int userId)
        {
            var query = _orderRepository.Query()
                .Include(o => o.OrderFin)
                .Include(o => o.Customer)
                .Include(o => o.OrderOps)
                .Include(o => o.Addresses)
                .Where(o => o.OrderFin != null &&
                           (// Đang cầm tiền hiện tại
                            o.OrderFin.SourceFeeCashierId == userId ||
                            o.OrderFin.DestFeeCashierId == userId ||
                            o.OrderFin.CodCashierId == userId ||
                            // Hoặc đã từng thu tiền ban đầu (Original Cashier)
                            o.OrderFin.OriginalSourceFeeCashierId == userId ||
                            o.OrderFin.OriginalDestFeeCashierId == userId ||
                            o.OrderFin.OriginalCodCashierId == userId));

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

                // Tìm kiếm theo từ khóa (mã đơn hàng, mã đối tác)
                // if (search.Keyword != null)
                // {
                //     string keyword = search.Keyword;
                //     keyword = keyword.Trim().ToLower();
                //     if (!string.IsNullOrWhiteSpace(keyword))
                //     {
                //         query = query.Where(x => x.Code.ToLower().Contains(keyword) ||
                //                                x.PartnerCode.ToLower().Contains(keyword));
                //     }
                // }

                // Lọc theo thời gian thu tiền (SourceFeeCollectedTime, DestFeeCollectedTime, CodCollectedTime)
                if (search.CollectedStart != null && search.CollectedEnd != null)
                {
                    DateTimeOffset start = search.CollectedStart;
                    DateTimeOffset end = search.CollectedEnd;
                    DateTimeOffset startParam = start.StartOfDay();
                    DateTimeOffset endParam = end.EndOfDay();
                    query = query.Where(x =>
                        (x.OrderFin.SourceFeeCollectedTime != null && x.OrderFin.SourceFeeCollectedTime >= startParam && x.OrderFin.SourceFeeCollectedTime <= endParam) ||
                        (x.OrderFin.DestFeeCollectedTime != null && x.OrderFin.DestFeeCollectedTime >= startParam && x.OrderFin.DestFeeCollectedTime <= endParam) ||
                        (x.OrderFin.CodCollectedTime != null && x.OrderFin.CodCollectedTime >= startParam && x.OrderFin.CodCollectedTime <= endParam));
                }


                // // Lọc theo loại tiền đang cầm
                // if (search.CashierType != null)
                // {
                //     string cashierType = search.CashierType;
                //     switch (cashierType.ToLower())
                //     {
                //         case "source":
                //             query = query.Where(x => x.OrderFin.SourceFeeCashierId == userId);
                //             break;
                //         case "dest":
                //             query = query.Where(x => x.OrderFin.DestFeeCashierId == userId);
                //             break;
                //         case "cod":
                //             query = query.Where(x => x.OrderFin.CodCashierId == userId);
                //             break;
                //     }
                // }
            }

            // Sắp xếp mặc định theo ngày tạo giảm dần
            param.Sort = new Sort() { Predicate = "Id", Reverse = true };

            var gridData = await query.ToSmartTableResultAsync(param, x => x.ToDriverFinOrderItem(userId));

            // Enrich địa chỉ với tên phường/quận/tỉnh
            await EnrichAddressesAsync(gridData.Items);

            return gridData;
        }

        /// <summary>
        /// Enrich thông tin địa chỉ đầy đủ (phường/quận/tỉnh) cho danh sách DriverFinOrderItem
        /// </summary>
        private async Task EnrichAddressesAsync(IEnumerable<DriverFinOrderItem> items)
        {
            if (items == null || !items.Any())
                return;

            // Lấy tất cả WardId từ SourceAddress và DestAddress
            var wardIds = items
                .SelectMany(i => new[] { i.SourceWardId, i.DestWardId })
                .Where(id => id > 0)
                .Distinct()
                .ToList();

            if (!wardIds.Any())
                return;

            var fullAddresses = await _locationService.GetFullAddress(wardIds, 3);

            foreach (var item in items)
            {
                // Enrich SourceAddress
                if (item.SourceWardId > 0)
                {
                    var fullAddress = fullAddresses.FirstOrDefault(f => f.Id == item.SourceWardId);
                    if (fullAddress != null && fullAddress.Id > 0)
                    {
                        item.SourceAddress = !string.IsNullOrEmpty(item.SourceAddress)
                            ? $"{item.SourceAddress}, {fullAddress.FullAddress}"
                            : fullAddress.FullAddress;

                        // Cập nhật RouteName từ CityName
                        if (!string.IsNullOrEmpty(fullAddress.CityName))
                            item.RouteName = fullAddress.CityName;
                    }
                }

                // Enrich DestAddress
                if (item.DestWardId > 0)
                {
                    var fullAddress = fullAddresses.FirstOrDefault(f => f.Id == item.DestWardId);
                    if (fullAddress != null && fullAddress.Id > 0)
                    {
                        item.DestAddress = !string.IsNullOrEmpty(item.DestAddress)
                            ? $"{item.DestAddress}, {fullAddress.FullAddress}"
                            : fullAddress.FullAddress;

                        // Cập nhật RouteName
                        if (!string.IsNullOrEmpty(fullAddress.CityName))
                        {
                            item.RouteName = !string.IsNullOrEmpty(item.RouteName)
                                ? $"{item.RouteName} - {fullAddress.CityName}"
                                : fullAddress.CityName;
                        }
                    }
                }

                // Cập nhật ContactAddress theo AddressType
                if (item.AddressType == "Source")
                    item.ContactAddress = item.SourceAddress;
                else if (item.AddressType == "Dest")
                    item.ContactAddress = item.DestAddress;
            }
        }

    }
}
