using Lada.Framework.Data.Domains.Settings;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Settings;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Settings;
using Ladaer.BackEnd.Infrastructures.DTO;
using Microsoft.EntityFrameworkCore;
using Lada.Framework.Data.Domains;
using Newtonsoft.Json.Linq;
using Lada.Framework.Infrastructures.Helpers;

namespace Ladaer.BackEnd.Infrastructures.Services.Settings
{
    public interface ICallPathService
    {
        /// <summary>
        /// Lấy thông tin CallPath theo Id.
        /// </summary>
        /// <param name="id">Id của CallPath.</param>
        /// <returns>Thông tin CallPath.</returns>
        Task<CallPathModel> GetByIdAsync(int id);

        /// <summary>
        /// Tạo mới CallPath.
        /// </summary>
        /// <param name="callPath">Thông tin CallPath cần tạo.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> CreateOrUpdateAsync(CallPathModel callPath);

        /// <summary>
        /// Xóa CallPath.
        /// </summary>
        /// <param name="id">Id của CallPath cần xóa.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> DeleteAsync(int id);

        /// <summary>
        /// Tìm kiếm CallPath theo điều kiện lọc và phân trang.
        /// </summary>
        /// <param name="param">Tham số phân trang và điều kiện lọc.</param>
        /// <returns>Kết quả phân trang chứa danh sách CallPath.</returns>
        Task<SmartTableResult<CallPathItem>> SearchAsync(SmartTableParam param);

        Task<List<CallPathItem>> GetAllAsync();
    }


    /// <summary>
    /// Triển khai dịch vụ quản lý CallPath.
    /// </summary>
    public class CallPathService : ICallPathService
    {
        private readonly IRepository<CallPath> _callPathRepository;
        private const string EntityName = "CallPath";

        public CallPathService(
            IRepository<CallPath> callPathRepository)
        {
            _callPathRepository = callPathRepository;
        }

        /// <inheritdoc/>
        public async Task<CallPathModel> GetByIdAsync(int id)
        {
            var result = new CallPathModel();
            if (id <= 0)
            {
                return result;
            }
            var callPathForUpdate = await _callPathRepository.Query()
                .Include(x => x.CallPathVersion)
                .FirstOrDefaultAsync(c => c.Id == id);
            if (callPathForUpdate == null || callPathForUpdate.Id <= 0)
            {
                return result;
            }
            return callPathForUpdate.ToModel();
        }

        /// <inheritdoc/>
        public async Task<BaseResult> CreateOrUpdateAsync(CallPathModel callPath)
        {
            try
            {
                if (callPath == null)
                    ArgumentNullException.ThrowIfNull(callPath);

                var entity = callPath.MapTo<CallPathModel, CallPath>();
                if (entity.Id > 0)
                {
                    return await UpdateAsync(entity);
                }
                else
                {
                    return await CreateAsync(entity);
                }
            }
            catch (Exception ex)
            {
                return new BaseResult
                {
                    Result = Result.Failed,
                    Message = ex.Message
                };
            }
        }

        /// <inheritdoc/>
        private async Task<BaseResult> UpdateAsync(CallPath callPath)
        {
            try
            {
                ArgumentNullException.ThrowIfNull(callPath);

                await _callPathRepository.UpdateAsync(callPath);
                return new BaseResult { Result = Result.Success };
            }
            catch (Exception ex)
            {
                return new BaseResult
                {
                    Result = Result.Failed,
                    Message = ex.Message
                };
            }
        }

        /// <inheritdoc/>
        private async Task<BaseResult> CreateAsync(CallPath callPath)
        {
            try
            {
                ArgumentNullException.ThrowIfNull(callPath);

                await _callPathRepository.InsertAsync(callPath);
                return new BaseResult { Result = Result.Success };
            }
            catch (Exception ex)
            {
                return new BaseResult
                {
                    Result = Result.Failed,
                    Message = ex.Message
                };
            }
        }

        /// <inheritdoc/>
        public async Task<BaseResult> DeleteAsync(int id)
        {
            var result = new BaseResult();
            if (id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Yêu cầu xóa không hợp lệ";
                return result;
            }
            var callPathForUpdate = await _callPathRepository.Query().FirstOrDefaultAsync(c => c.Id == id);
            if (callPathForUpdate == null || callPathForUpdate.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy danh mục yêu cầu";
                return result;
            }

            try
            {
                // Cập nhật thông tin chung của thực thể
                callPathForUpdate = callPathForUpdate.UpdateCommonInt();
                var delResult = await _callPathRepository.DeleteAsync(callPathForUpdate);
                if (delResult <= 0)
                {
                    result.Result = Result.SystemError;
                    result.Message = "Hệ thống không thể thực hiện yêu cầu lúc này, vui lòng thử lại sau!";
                    return result;
                }
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }
            return result;
        }

        /// <inheritdoc/>
        public async Task<SmartTableResult<CallPathItem>> SearchAsync(SmartTableParam param)
        {
            IQueryable<CallPath> query = _callPathRepository.Query()
                .Include(x => x.CallPathVersion);

            if (param.Search?.PredicateObject != null)
            {
                var search = param.Search.PredicateObject as JObject;
                if (search != null)
                {
                    // Apply search filter if keyword is provided
                    if (search["Keyword"] != null)
                    {
                        string keyword = search["Keyword"]?.ToString()?.Trim()?.ToLower() ?? string.Empty;
                        if (!string.IsNullOrEmpty(keyword))
                        {
                            query = query.Where(x =>
                                (x.Name != null && x.Name.ToLower().Contains(keyword)) ||
                                (x.RelativePath != null && x.RelativePath.ToLower().Contains(keyword)) ||
                                (x.Description != null && x.Description.ToLower().Contains(keyword)) ||
                                (x.CallPathVersion != null && (x.CallPathVersion.Version.Contains(keyword) || x.CallPathVersion.Build.Contains(keyword) || x.CallPathVersion.Domain.Contains(keyword)))
                            );
                        }
                    }

                    // Apply version filter if provided
                    if (search["Version"] != null)
                    {
                        string version = search["Version"]?.ToString()?.Trim() ?? string.Empty;
                        if (!string.IsNullOrEmpty(version))
                        {
                            query = query.Where(x => x.CallPathVersion != null && x.CallPathVersion.Version == version);
                        }
                    }

                    // Apply build filter if provided
                    if (search["Build"] != null)
                    {
                        string build = search["Build"]?.ToString()?.Trim() ?? string.Empty;
                        if (!string.IsNullOrEmpty(build))
                        {
                            query = query.Where(x => x.CallPathVersion != null && x.CallPathVersion.Build == build);
                        }
                    }

                    // Apply date range filter if provided
                    if (search["CreatedStart"] != null && search["CreatedEnd"] != null)
                    {
                        if (DateTimeOffset.TryParse(search["CreatedStart"]?.ToString(), out DateTimeOffset start) &&
                            DateTimeOffset.TryParse(search["CreatedEnd"]?.ToString(), out DateTimeOffset end))
                        {
                            // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                            DateTime startDate = start.ToLocalTime().DateTime.StartOfDay();
                            DateTime endDate = end.ToLocalTime().DateTime.EndOfDay();
                            query = query.Where(x => x.CreatedTime >= startDate && x.CreatedTime <= endDate);
                        }
                    }
                }
            }

            // Apply sorting
            param.Sort = new Sort { Predicate = "Id", Reverse = true };
            var gridData = await query.ToSmartTableResultAsync(param, x => x.ToItem());
            return gridData;
        }

        public async Task<List<CallPathItem>> GetAllAsync()
        {
            IQueryable<CallPath> query = _callPathRepository.Query()
                .Include(x => x.CallPathVersion);
            return await query.Select(x => x.ToItem()).ToListAsync();
        }
    }
}