using Lada.Framework.Data.Domains.Crm;
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.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Crm;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Crm;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Crm;
using Ladaer.BackEnd.Infrastructures.DTO.Profiles;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.Crm
{
    /// <summary>
    /// Interface cho CallLog Service
    /// </summary>
    public interface ICallLogService
    {
        /// <summary>
        /// Tìm kiếm call log
        /// </summary>
        /// <param name="param">Tham số tìm kiếm</param>
        /// <returns>Kết quả tìm kiếm</returns>
        Task<SmartTableResult<CallLogItem>> Search(SmartTableParam param);

        /// <summary>
        /// Lấy call log theo ID
        /// </summary>
        /// <param name="id">ID của call log</param>
        /// <returns>Thông tin call log</returns>
        Task<CallLogModel> GetById(int id);

        /// <summary>
        /// Tạo/cập nhật call log
        /// </summary>
        /// <param name="model">Thông tin call log</param>
        /// <returns>Kết quả của thao tác</returns>
        Task<CallLogResult> CreateOrUpdate(CallLogModel model);

        /// <summary>
        /// Tạo call log mới
        /// </summary>
        /// <param name="model">Thông tin call log</param>
        /// <returns>Kết quả của thao tác</returns>
        Task<CallLogResult> Create(CallLogModel model);

        /// <summary>
        /// Cập nhật call log
        /// </summary>
        /// <param name="callLog">Thông tin call log</param>
        /// <returns>Kết quả của thao tác</returns>
        Task<CallLogResult> Update(CallLog callLog);

        /// <summary>
        /// Xóa call log
        /// </summary>
        /// <param name="id">ID của call log</param>
        /// <returns>Kết quả của thao tác</returns>
        Task<BaseResult> Delete(int id);
    }

    /// <summary>
    /// CallLog Service Implementation
    /// </summary>
    public class CallLogService : ICallLogService
    {
        private readonly IRepository<CallLog> _callLogRepository;
        private readonly IUserRepository<User> _userRepository;

        public CallLogService(IRepository<CallLog> callLogRepository, IUserRepository<User> userRepository)
        {
            _callLogRepository = callLogRepository;
            _userRepository = userRepository;
        }

        /// <summary>
        /// Tìm kiếm call log với phân trang
        /// </summary>
        public async Task<SmartTableResult<CallLogItem>> Search(SmartTableParam param)
        {
            var query = _callLogRepository.Query()
                .Where(x => x.FromDN == "10000");

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

                    // Tìm kiếm theo từ khóa
                    if (search.Keyword != null)
                    {
                        string keyword = search.Keyword;
                        keyword = keyword.Trim().ToLower();
                        if (!string.IsNullOrEmpty(keyword))
                        {
                            query = query.Where(x => (x.FromNo != null && x.FromNo.Contains(keyword))
                                        || (x.ToNo != null && x.ToNo.Contains(keyword))
                                        || (x.FromDispName != null && x.FromDispName.ToLower().Contains(keyword))
                                        || (x.ToDispName != null && x.ToDispName.ToLower().Contains(keyword))
                                        || (x.CallID != null && x.CallID.Contains(keyword))
                                        || (x.HistoryID != null && x.HistoryID.Contains(keyword)));
                        }
                    }

                    // Tìm kiếm theo khoảng thời gian
                    if (search.TimeStart != null && search.TimeEnd != null)
                    {
                        DateTimeOffset start = search.TimeStart;
                        DateTimeOffset end = search.TimeEnd;
                        // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                        DateTime startParam = start.ToLocalTime().DateTime.StartOfDay();
                        DateTime endParam = end.ToLocalTime().DateTime.EndOfDay();
                        query = query.Where(x => x.TimeStart >= startParam && x.TimeStart <= endParam);
                    }

                    // Tìm kiếm theo trạng thái Lead
                    if (search.LeadStatus != null)
                    {
                        string leadStatusValue = search.LeadStatus.ToString();
                        if (!string.IsNullOrEmpty(leadStatusValue) && Enum.TryParse<LeadStatus>(leadStatusValue, out LeadStatus status))
                        {
                            query = query.Where(x => x.LeadStatus == status);
                        }
                    }

                    // Tìm kiếm theo loại cuộc gọi
                    if (search.CallType != null)
                    {
                        string callType = search.CallType;
                        if (!string.IsNullOrEmpty(callType))
                        {
                            query = query.Where(x => x.CallType == callType);
                        }

                    }

                    // Tìm kiếm theo số điện thoại nguồn
                    if (search.FromNo != null)
                    {
                        string fromNo = search.FromNo;
                        if (!string.IsNullOrEmpty(fromNo))
                        {
                            query = query.Where(x => x.FromNo != null && x.FromNo.Contains(fromNo));
                        }

                    }

                    // Tìm kiếm theo số điện thoại đích
                    if (search.ToNo != null)
                    {
                        string toNo = search.ToNo;
                        if (!string.IsNullOrEmpty(toNo))
                        {
                            query = query.Where(x => x.ToNo != null && x.ToNo.Contains(toNo));
                        }


                    }
                }

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

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

                return gridData;
            }
            catch (Exception)
            {
                var gridData = new SmartTableResult<CallLogItem>();
                return gridData;
            }
        }

        /// <summary>
        /// Lấy call log theo ID
        /// </summary>
        public async Task<CallLogModel> GetById(int id)
        {
            var callLog = await _callLogRepository.Query()
                .FirstOrDefaultAsync(x => x.Id == id);

            return callLog?.ToModel() ?? new CallLogModel();
        }

        /// <summary>
        /// Tạo hoặc cập nhật call log
        /// </summary>
        public async Task<CallLogResult> CreateOrUpdate(CallLogModel model)
        {
            var callLog = model.ToEntity();

            if (callLog.Id > 0)
            {
                // Cập nhật
                return await Update(callLog);
            }
            else
            {
                // Thêm mới
                return await Create(model);
            }
        }

        /// <summary>
        /// Tạo call log mới
        /// </summary>
        public async Task<CallLogResult> Create(CallLogModel model)
        {
            var result = new CallLogResult();
            var currentTime = DateTimeHelper.CurrentTime();

            var callLog = model.ToEntity();
            callLog.CreatedTime = currentTime;
            callLog.UpdatedTime = currentTime;

            // Mapping FinalDN với User nếu có FinalDN
            if (!string.IsNullOrEmpty(callLog.FinalDN))
            {
                var user = await _userRepository.Query()
                    .FirstOrDefaultAsync(u => u.FinalDN == callLog.FinalDN);

                if (user != null)
                {
                    callLog.UserId = user.Id;
                    callLog.UserName = user.FullName ?? user.UserName ?? "";
                }
            }

            try
            {
                await _callLogRepository.InsertAsync(callLog);
                result.Id = callLog.Id;
                result.Result = Result.Success;
                result.Message = "Tạo call log thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }

            return result;
        }

        /// <summary>
        /// Cập nhật call log
        /// </summary>
        public async Task<CallLogResult> Update(CallLog callLog)
        {
            var result = new CallLogResult();
            var currentTime = DateTimeHelper.CurrentTime();

            try
            {
                var existingCallLog = await _callLogRepository.Query()
                    .FirstOrDefaultAsync(x => x.Id == callLog.Id);

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

                // Cập nhật các trường
                existingCallLog.HistoryID = callLog.HistoryID;
                existingCallLog.CallID = callLog.CallID;
                existingCallLog.Duration = callLog.Duration;
                existingCallLog.TimeStart = callLog.TimeStart;
                existingCallLog.TimeAnswered = callLog.TimeAnswered;
                existingCallLog.TimeEnd = callLog.TimeEnd;
                existingCallLog.ReasonTerminated = callLog.ReasonTerminated;
                existingCallLog.FromNo = callLog.FromNo;
                existingCallLog.ToNo = callLog.ToNo;
                existingCallLog.FromDN = callLog.FromDN;
                existingCallLog.ToDN = callLog.ToDN;
                existingCallLog.DialNo = callLog.DialNo;
                existingCallLog.ReasonChanged = callLog.ReasonChanged;
                existingCallLog.FinalNumber = callLog.FinalNumber;
                existingCallLog.FinalDN = callLog.FinalDN;

                // Mapping FinalDN với User nếu có FinalDN
                if (!string.IsNullOrEmpty(callLog.FinalDN))
                {
                    var user = await _userRepository.Query()
                        .FirstOrDefaultAsync(u => u.FinalDN == callLog.FinalDN);

                    if (user != null)
                    {
                        existingCallLog.UserId = user.Id;
                        existingCallLog.UserName = user.FullName ?? user.UserName ?? "";
                    }
                    else
                    {
                        existingCallLog.UserId = null;
                        existingCallLog.UserName = null;
                    }
                }
                else
                {
                    existingCallLog.UserId = null;
                    existingCallLog.UserName = null;
                }

                existingCallLog.BillCode = callLog.BillCode;
                existingCallLog.BillRate = callLog.BillRate;
                existingCallLog.BillCost = callLog.BillCost;
                existingCallLog.BillName = callLog.BillName;
                existingCallLog.Chain = callLog.Chain;
                existingCallLog.FromType = callLog.FromType;
                existingCallLog.ToType = callLog.ToType;
                existingCallLog.FinalType = callLog.FinalType;
                existingCallLog.FromDispName = callLog.FromDispName;
                existingCallLog.ToDispName = callLog.ToDispName;
                existingCallLog.FinalDispName = callLog.FinalDispName;
                existingCallLog.MissedQueueCalls = callLog.MissedQueueCalls;
                existingCallLog.CallType = callLog.CallType;
                existingCallLog.LeadStatus = callLog.LeadStatus;
                existingCallLog.StatusContent = callLog.StatusContent;
                existingCallLog.UpdatedTime = currentTime;
                existingCallLog.UpdatedBy = callLog.UpdatedBy;
                existingCallLog.UpdatedByUserName = callLog.UpdatedByUserName;

                await _callLogRepository.UpdateAsync(existingCallLog);

                result.Id = existingCallLog.Id;
                result.Result = Result.Success;
                result.Message = "Cập nhật call log thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }

            return result;
        }

        /// <summary>
        /// Xóa call log (soft delete)
        /// </summary>
        public async Task<BaseResult> Delete(int id)
        {
            var result = new BaseResult();

            try
            {
                var callLog = await _callLogRepository.Query()
                    .FirstOrDefaultAsync(x => x.Id == id);

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

                callLog.IsDeleted = true;
                callLog.UpdatedTime = DateTimeHelper.CurrentTime();

                await _callLogRepository.UpdateAsync(callLog);

                result.Result = Result.Success;
                result.Message = "Xóa call log thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }
    }
}
