using AutoMapper;
using Entities.Contracts;
using SharedDATA.Api;
using System.Linq.Expressions;
using System.Linq;
using Entities.DTO;

namespace TechHelper.Services.Beta
{
    public class QuestionService : IQuestionService
    {
        private readonly IUnitOfWork _work;
        private readonly IMapper _mapper;
        private readonly IExamService _examService;

        public QuestionService(IUnitOfWork work, IMapper mapper, IExamService examService)
        {
            _work = work;
            _mapper = mapper;
            _examService = examService;
        }

        #region CRUD Operations

        /// <summary>
        /// 创建新题目
        /// </summary>
        /// <param name="model">题目DTO</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> AddAsync(QuestionDto model)
        {
            try
            {
                // 业务逻辑校验：检查题目是否已存在
                var existingQuestion = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Title == model.Title && !q.IsDeleted
                );

                if (existingQuestion != null)
                {
                    return ApiResponse.Error($"题目 '{model.Title}' 已存在，请勿重复添加。");
                }

                var newQuestion = _mapper.Map<Question>(model);

                // 插入数据
                await _work.GetRepository<Question>().InsertAsync(newQuestion);
                await _work.SaveChangesAsync();

                return ApiResponse.Success("题目添加成功。", newQuestion);
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"添加题目失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 根据ID获取题目
        /// </summary>
        /// <param name="id">题目ID</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> GetAsync(Guid id)
        {
            try
            {
                var question = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Id == id && !q.IsDeleted
                );

                if (question == null)
                {
                    return ApiResponse.Error($"找不到 ID 为 {id} 的题目。");
                }

                return ApiResponse.Success(result: question);
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"获取题目时发生错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取所有题目（支持分页和搜索）
        /// </summary>
        /// <param name="query">查询参数</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> GetAllAsync(QueryParameter query)
        {
            try
            {
                var repository = _work.GetRepository<Question>();

                if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
                {
                    var questions = await repository.GetPagedListAsync(
                        predicate: q => q.Title.Contains(query.Search) && !q.IsDeleted,
                        pageSize: query.PageSize,
                        pageIndex: query.PageIndex
                    );
                    var questionDtosFiltered = _mapper.Map<IEnumerable<QuestionDto>>(questions.Items);
                    return new ApiResponse(true, questionDtosFiltered);
                }
                else
                {
                    var questions = await repository.GetPagedListAsync(
                        predicate: q => !q.IsDeleted,
                        pageSize: query.PageSize,
                        pageIndex: query.PageIndex
                    );
                    var questionDtos = _mapper.Map<IEnumerable<QuestionDto>>(questions.Items);
                    return new ApiResponse(true, questionDtos);
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse($"获取所有题目时发生错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 更新题目信息
        /// </summary>
        /// <param name="model">题目DTO</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> UpdateAsync(QuestionDto model)
        {
            try
            {
                // 检查题目是否存在
                var existingQuestion = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Id == model.Id && !q.IsDeleted
                );

                if (existingQuestion == null)
                {
                    return ApiResponse.Error($"找不到 ID 为 {model.Id} 的题目，无法更新。");
                }

                // 检查题目文本是否与其他题目重复
                var duplicateCheck = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Id != model.Id && q.Title == model.Title && !q.IsDeleted
                );

                if (duplicateCheck != null)
                {
                    return ApiResponse.Error($"题目文本 '{model.Title}' 已被其他题目占用，请修改。");
                }

                // 使用mapper更新实体属性，保留系统字段
                _mapper.Map(model, existingQuestion);
                existingQuestion.UpdatedAt = DateTime.UtcNow;

                // 更新数据
                _work.GetRepository<Question>().Update(existingQuestion);
                await _work.SaveChangesAsync();

                return ApiResponse.Success("题目更新成功。", existingQuestion);
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"更新题目失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 删除题目（软删除）
        /// </summary>
        /// <param name="id">题目ID</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> DeleteAsync(Guid id)
        {
            try
            {
                var questionToDelete = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Id == id && !q.IsDeleted
                );

                if (questionToDelete == null)
                {
                    return ApiResponse.Error($"找不到 ID 为 {id} 的题目，或者该题目已被删除。");
                }

                // 软删除
                questionToDelete.IsDeleted = true;
                questionToDelete.UpdatedAt = DateTime.UtcNow;

                _work.GetRepository<Question>().Update(questionToDelete);
                await _work.SaveChangesAsync();

                return ApiResponse.Success($"ID 为 {id} 的题目已成功删除 (软删除)。");
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"删除题目时发生错误: {ex.Message}");
            }
        }

        #endregion

        #region Business Logic Methods

        /// <summary>
        /// 根据标题查找题目
        /// </summary>
        /// <param name="title">题目标题</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> FindByTitle(string title)
        {
            try
            {
                var question = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
                    predicate: q => q.Title == title && !q.IsDeleted
                );

                if (question == null)
                {
                    return ApiResponse.Error($"未找到题目 '{title}'。");
                }

                return ApiResponse.Success(result: question);
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"查找题目时出现问题: {ex.Message}");
            }
        }

        /// <summary>
        /// 批量检查题目标题是否存在
        /// </summary>
        /// <param name="titles">题目标题集合</param>
        /// <returns>API响应结果</returns>
        public async Task<ApiResponse> CheckTitlesExistence(IEnumerable<string> titles)
        {
            try
            {
                if (titles == null || !titles.Any())
                {
                    return ApiResponse.Success("未指定查询的题目文本，返回空结果。", new Dictionary<string, bool>());
                }

                var distinctTitles = titles.Distinct(StringComparer.OrdinalIgnoreCase).ToList();

                var existingQuestions = await _work.GetRepository<Question>().GetAllAsync(
                    predicate: q => distinctTitles.Contains(q.Title) && !q.IsDeleted
                );

                var existingQuestionTexts = new HashSet<string>(
                    existingQuestions.Select(q => q.Title), 
                    StringComparer.OrdinalIgnoreCase
                );

                var resultDictionary = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
                foreach (var title in titles)
                {
                    resultDictionary[title] = existingQuestionTexts.Contains(title);
                }

                return ApiResponse.Success(result: resultDictionary);
            }
            catch (Exception ex)
            {
                return ApiResponse.Error($"批量查找题目存在性时出现问题: {ex.Message}");
            }
        }

        #endregion
    }

    /// <summary>
    /// 表达式构建器扩展类
    /// </summary>
    public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> And<T>(
            this Expression<Func<T, bool>> first, 
            Expression<Func<T, bool>> second)
        {
            var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(
                Expression.AndAlso(first.Body, invokedExpr), 
                first.Parameters
            );
        }

        public static Expression<Func<T, bool>> Or<T>(
            this Expression<Func<T, bool>> first, 
            Expression<Func<T, bool>> second)
        {
            var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(
                Expression.OrElse(first.Body, invokedExpr), 
                first.Parameters
            );
        }

        public static Expression<Func<T, bool>> True<T>() => f => true;
        public static Expression<Func<T, bool>> False<T>() => f => false;
    }
}
