using Mapster;
using QYZH.InteractiveMagazine.Common.Extensions;
using QYZH.InteractiveMagazine.Infrastructure.OSS;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Dto.Journal;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;
using Yitter.IdGenerator;


namespace QYZH.InteractiveMagazine.Service;

public class JournalPageTaskService(BaseRepository<Journal> journalRepository, OssService ossService, BaseRepository<JournalPageTaskAnswer> answerRepository) : BaseRepository<JournalPageTask>, IJournalPageTaskService
{
    public async Task<long?> InsertAsync(JournalPageTaskAddInput input)
    {
        var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
        BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能添加题目", ResultCode.CONFLICT);

        var map = input.Adapt<JournalPageTask>();
        map.Id = YitIdHelper.NextId();
        map.GroupId = map.Id;
        map.NeedAiProcess = input.NeedAiProcess;
        var no = input.No.Split('-').Select(int.Parse).ToArray();
        if (no.Last() >= 2)
        {
            var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
            var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
            BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND);
            map.GroupId = groupTask.GroupId;
            map.Type = groupTask.Type;
        }

        await base.InsertAsync(map);

        return map?.Id;
    }


    public async Task<bool> UpdateAsync(JournalPageTaskUpdateInput input)
    {
        var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
        BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能修改题目", ResultCode.CONFLICT);

        var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
        BusinessException.ThrowIf(task.IsNull(), "未找到关联的题号", ResultCode.NOT_FOUND);

        var sameTask = await base.Queryable().Where(w => w.No == input.No && w.JournalId == input.JournalId && w.Id != input.Id).FirstAsync();
        BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目", ResultCode.CONFLICT);


        var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";

        // 题目内容处理
        input.Task = Deal(task.Task, input.Task, key, "task");

        task.Type = input.Type;
        task.Task = input.Task;
        task.Points = input.Points;
        task.GrowthPoint = input.GrowthPoint;
        task.Comprehension = input.Comprehension;
        task.Judgment = input.Judgment;
        task.Expression = input.Expression;
        task.Persuasiveness = input.Persuasiveness;
        task.AnswerTime = input.AnswerTime;
        task.Prompt = input.Prompt;
        task.NeedAiProcess = input.NeedAiProcess;
        

        var no = input.No.Split('-').Select(int.Parse).ToArray();
        if (no.Last() >= 2)
        {
            var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
            var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
            BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND);
            task.GroupId = groupTask.GroupId;
            task.Type = groupTask.Type;
        }

        var taskResult = await base.Updateable(task).ExecuteCommandAsync() > 0;

        return taskResult;
    }

    public async Task<JournalPageTaskOutput> DetailAsync(long id)
    {
        var task = await base.Queryable().Where(w => w.Id == id).FirstAsync();
        if (task == null) return null;

        var data = new JournalPageTaskOutput
        {
            Id = task.Id,
            JournalId = task.JournalId,
            JournalPageId = task.JournalPageId,
            No = task.No,
            Task =task.Task,
            Type = task.Type,
            Points = task.Points,
            GrowthPoint = task.GrowthPoint,
            Comprehension = task.Comprehension,
            Judgment = task.Judgment,
            Expression = task.Expression,
            Persuasiveness = task.Persuasiveness,
            AnswerTime = task.AnswerTime,
            Prompt = task.Prompt,
            NeedAiProcess = task.NeedAiProcess
        };

        // 查询答案列表
        var answers = await answerRepository.Queryable()
            .Where(a => a.JournalPageTaskId == id)
            .ToListAsync();

        data.Answers = answers.Select(a => new JournalTaskAnswerOutput
        {
            Id = a.Id,
            Answer = a.Answer,
            AnswerUrl = a.AnswerUrL
        }).ToList();

        return data;
    }

    public async Task<bool> DeleteAsync(long id)
    {
        var task = await base.Queryable().Where(w => w.Id == id).FirstAsync();
        BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);

        var key = $"journal/{task.JournalId}/{task.JournalPageId}/{id}";

        // 同时删除关联的答案记录
        await answerRepository.DeleteAsync(a => a.JournalPageTaskId == id);

        ossService.DeleteObject(key);

        return await base.DeleteAsync(d => d.Id == id);
    }

    public async Task<bool> ComplementAsync(JournalPageTaskComplementInput input)
    {
        var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
        BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);

        if (input.AudioUrl.NotNull())
        {
            var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.Id}/audio.{input.AudioUrl.ToExtension()}";
            ossService.CopyObject(input.AudioUrl, key);
            input.AudioUrl = key;
        }
        if (input.PointsUrl.NotNull())
        {
            var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.Id}/points.json";
            ossService.CopyObject(input.PointsUrl, key);
            input.PointsUrl = key;
        }
        return await Updateable(input.Adapt<JournalPageTask>()).Where(w => w.Id == input.Id).ExecuteCommandAsync() > 0;
    }

    public async Task<long> AddAnswerAsync(JournalTaskAnswerAddInput input)
    {
        var task = await base.Queryable().Where(w => w.Id == input.JournalPageTaskId).FirstAsync();
        BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);

        var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
        input.Answer = Deal(null, input.Answer, key, "answer");
        input.AnswerUrl = Deal(null, input.AnswerUrl, key, "answerUrl");

        var entity = new JournalPageTaskAnswer
        {
            JournalPageTaskId = input.JournalPageTaskId,
            Answer = input.Answer,
            AnswerUrL = input.AnswerUrl,
            CreatedBy = "System",
            CreatedAt = DateTime.Now,
            IsDeleted = false
        };
        await answerRepository.InsertAsync(entity);
        return entity.Id;
    }

    public async Task<bool> UpdateAnswerAsync(JournalTaskAnswerUpdateInput input)
    {
        var answer = await answerRepository.Queryable().Where(a => a.Id == input.Id).FirstAsync();
        BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND);

        var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
        var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";

        input.Answer = Deal(answer.Answer, input.Answer, key, "answer");
        input.AnswerUrl = Deal(answer.AnswerUrL, input.AnswerUrl, key, "answerUrl");

        return await answerRepository.Updateable()
            .SetColumns(a => a.Answer == input.Answer)
            .SetColumns(a => a.AnswerUrL == input.AnswerUrl)
            .Where(a => a.Id == input.Id)
            .ExecuteCommandAsync() > 0;
    }

    public async Task<bool> DeleteAnswerAsync(long id)
    {
        var answer = await answerRepository.Queryable().Where(a => a.Id == id).FirstAsync();
        BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND);

        var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
        var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";

        // 清理OSS文件
        Deal(answer.Answer, "", key, "answer");
        Deal(answer.AnswerUrL, "", key, "answerUrl");

        return await answerRepository.DeleteAsync(a => a.Id == id);
    }

    private string Deal(string oldUrls, string newUrls, string key, string type)
    {
        // 如果 newUrls 为空，则直接返回
        if (newUrls.IsNull()) return null;

        // 处理 oldUrls 为 null 的情况，将其视为空字符串
        var oldTaskUrls = oldUrls.AllUrl().Distinct();
        var taskUrls = newUrls.AllUrl().Distinct().Select(s => s.RemoveDomain());

        // 删除不存在的（存在于旧集合但不在新集合中）
        var removedUrls = oldTaskUrls.Except(taskUrls).ToList();
        ossService.DeleteObjects(removedUrls);

        // 添加新增的（存在于新集合但不在旧集合中）
        var addedUrls = taskUrls.Except(oldTaskUrls).ToList();
        foreach (var item in addedUrls)
        {
            var value = $"{key}/{type}/{YitIdHelper.NextId()}.{item.ToExtension()}";
            ossService.CopyObject(item, value);

            newUrls = newUrls.Replace(item, value);

        }
        return newUrls;
    }
}
