
using Aliyun.Acs.Core.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using QYZH.InteractiveMagazine.Common.Extensions;
using QYZH.InteractiveMagazine.Common.Helpers;
using QYZH.InteractiveMagazine.Infrastructure.OSS;
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
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 System.Diagnostics;
using System.Net;
using Yitter.IdGenerator;

namespace QYZH.InteractiveMagazine.Service;

public class JournalPageService(BaseRepository<Journal> JournalRepository,
                            OssService ossService,
                            IHttpClientFactory httpClientFactory,
                            IConfiguration configuration,
                            IRabbitMQService rabbitMqService,
                            ILogger<AiBasePromptService> logger,
                            BaseRepository<JournalPage> JournalPageRepository,
                            BaseRepository<JournalPageTask> JournalPageTaskRepository,
                            BaseRepository<JournalPageTaskAnswer> JournalPageTaskAnswerRepository) : BaseRepository<JournalPage>, IJournalPageService
{

    public async Task<long> InsertAsync(JournalAddV2Input input)
    {

        var Journal = await JournalRepository.Queryable().Where(w => w.Id == input.JournalId).FirstAsync();
        BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);

        BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改", ResultCode.CONFLICT);

        var pages = new List<JournalPage>();
        //var dotMatrixpages = new List<DotMatrixPage>();

        //var dotMatrixpage = new DotMatrixPage()
        //{
        //    Id = YitIdHelper.NextId(),
        //    DotMatrixNoteJournalId = input.JournalId,
        //    WidthMilliMeter = Journal.Width,
        //    HightMilliMeter = Journal.Height,
        //};

        var pageTemp = new JournalPage()
        {
            JournalId = input.JournalId,
            JournalCatalogId = input.JournalCatalogId,
            //DotMatrixPageId = dotMatrixpage.Id,
            Url = input.Url,
            PageNum = input.PageNum,
        };

        //dotMatrixpages.Add(dotMatrixpage);
        pages.Add(pageTemp);

        await UseTranAsync(async () =>
        {
            //using var uow = Context.Ado.BeginTran();
            var pageData = await base.InsertRangeAsync(pages);
            BusinessException.ThrowIf(pageData.IsNull(), "创建页失败", ResultCode.GLOBAL_ERROR);

            //var result = await dotMatrixPageRepository.InsertRangeAsync(dotMatrixpages);
            //BusinessException.ThrowIf(result, "创建点阵页失败");
        });

        return pages.Count; // 返回主目录ID
    }

    public async Task<bool> UpdateAsync(PageLayoutInput input)
    {
        var page = await Queryable().Where(w => w.Id == input.Id).FirstAsync();
        BusinessException.ThrowIf(page == null, "不存在此页", ResultCode.NOT_FOUND);

        var Journal = await JournalRepository.GetByIdAsync(page.JournalId);
        BusinessException.ThrowIf(Journal == null, "不存在此书", ResultCode.NOT_FOUND);

        BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改", ResultCode.CONFLICT);
        var transResult = await UseTranAsync(async () =>
        {
            //await dotMatrixPageRepository.Updateable().SetColumns(s => s.Area == input.Layout)
            //                                            .SetColumns(s => s.AreaPoints == dotMatrixPage.Area)
            //                                            .SetColumns(s => s.WidthMilliMeter == dotMatrixPage.WidthMilliMeter)
            //                                            .SetColumns(s => s.HightMilliMeter == dotMatrixPage.HightMilliMeter)
            //                                            .SetColumns(s => s.WidthDotMatrix == dotMatrixPage.WidthDotMatrix)
            //                                            .SetColumns(s => s.HightDotMatrix == dotMatrixPage.HightDotMatrix)
            //                                           .Where(w => w.Id == page.DotMatrixPageId).ExecuteCommandAsync();

            page.Layout = input.Layout;
            base.Update(page);

            input.TasksImages?.ForEach(it =>
            {
                var key = $"journal/{Journal.Id}/{input.Id}/{it.TaskId}/qustion.{it.Url.ToExtension()}";
                ossService.CopyObject(it.Url.RemoveDomain(), key);
                JournalPageTaskRepository.Updateable().SetColumns(s => s.TaskUrl, key).Where(w => w.Id == it.TaskId).ExecuteCommand();
            });
            return true;
        });
        return transResult;
    }

    /// <summary>
    /// 修改书页的点阵码
    /// </summary>
    /// <param name="JournalId"></param>
    /// <returns></returns>
    public async Task<bool> UpdatePageNoAsync(long JournalId)
    {
        var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == JournalId);
        BusinessException.ThrowIf(journalEntity == null, "不存在此期刊", ResultCode.NOT_FOUND);

        //如果书籍状态不等于“已归档”，“已废弃”，“已铺码”的情况下，就更新状态为“已铺码”
        BusinessException.ThrowIf((JournalStatusEnum)journalEntity.Status is JournalStatusEnum.Abandoned or JournalStatusEnum.Archive or JournalStatusEnum.Codeing, "当前【状态】不允许铺码", ResultCode.UNPROCESSABLE_ENTITY);

        var journalPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == JournalId).OrderBy(x => x.PageNum).ToListAsync();
        BusinessException.ThrowIf(journalPageList.Count == 0, "此期刊不存在任何书页", ResultCode.NOT_FOUND);

        var uploadPdfKey = journalEntity?.PdfUrl?.RemoveDomain();
        BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfKey), "此期刊上传的PDF路径错误，请检查期刊PDF文件是否上传成功", ResultCode.BAD_REQUEST);

        var uploadPdfUrl = DomainHelper.OssFullUrl(uploadPdfKey);
        BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfUrl), "此期刊上传的PDF路径错误，请检查期刊PDF文件是否上传成功", ResultCode.BAD_REQUEST);

        logger.LogInformation("uploadPdfUrl:" + uploadPdfUrl);
        //验证是否上传了PDF文件
        var isPdfExists = ossService.DoesObjectExist(uploadPdfKey);
        BusinessException.ThrowIf(!isPdfExists, "获取期刊上传的PDF文件失败，请检查PDF文件是否上传成功", ResultCode.GLOBAL_ERROR);

        journalEntity.Status = (int)JournalStatusEnum.Codeing;

        await JournalRepository.Updateable(journalEntity).UpdateColumns(x => new { x.Status, x.UpdatedAt }).ExecuteCommandAsync();

        var data = new JournalPagePrintDto
        {
            JournalId = JournalId,
            JournalPdfUrl = uploadPdfUrl,
            PageNum = [.. journalPageList.Select(x => x.PageNum)]
        };
        var msRes = await rabbitMqService.SendAsync(new RabbitMQSendParam { Exchange = "ex.journal", Queue = "mq.journal.dotcode.auto", RoutingKey = "rk.journal.dotcode.auto", Data = data });//发生消息
        return msRes;
    }
    /// <summary>
    /// 回调接口-自动铺码, 书页铺码后回调接口，更新书页的点阵码
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public async Task<bool> CallbackPageUpdatePageNo(JournalPagePrintDto request)
    {
        return await UseTranAsync(async () =>
        {
            var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == request.JournalId);
            BusinessException.ThrowIf(journalEntity == null, "不存在此书", ResultCode.NOT_FOUND);

            //如果书籍状态不等于“铺码中”则不允许回调接口更新点阵码
            BusinessException.ThrowIf(journalEntity.Status != (int)JournalStatusEnum.Codeing, "当前【状态】不允许修改铺码", ResultCode.UNPROCESSABLE_ENTITY);

            var bookPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == request.JournalId).OrderBy(x => x.PageNum).ToListAsync();

            BusinessException.ThrowIf(bookPageList.Count == 0, "此书不存在任何书页", ResultCode.NOT_FOUND);

            journalEntity.Status = (int)request.Status!.Value;
            journalEntity.UpdatedAt = DateTime.Now;

            //如果铺码成功了，并且之前已经有下载链接了，就删除原来的文件
            if (request.Status == JournalStatusEnum.CodeSuccess && !string.IsNullOrWhiteSpace(journalEntity.DownloadJournalPagePdfName))
            {
                //删除oss上原来的文件
                ossService.DeleteObject(journalEntity.DownloadJournalPagePdfName.RemoveDomain());
            }
            //如果铺码成功了，就更新下载链接,以及书页的点阵码
            if (request.Status == JournalStatusEnum.CodeSuccess)
            {
                journalEntity.DownloadJournalPagePdfName = request.DownloadJournalPagePdfName;

                BusinessException.ThrowIf(request.PageNo.Length != bookPageList.Count, $"点阵码条数与页码数量不匹配，点阵码条数：{request.PageNo.Length}，页码数量：{bookPageList.Count}", ResultCode.BAD_REQUEST);


                for (var i = 0; i < bookPageList.Count; i++)
                {
                    //让也页码和点阵码的顺序必须保持一致
                    bookPageList[i].PageNo = request.PageNo[i];
                    bookPageList[i].UpdatedAt = DateTime.Now;
                }

                await JournalPageRepository.UpdateRangeAsync(bookPageList);
            }

            await JournalRepository.Updateable(journalEntity).UpdateColumns(x => new { x.Status, x.DownloadJournalPagePdfName, x.UpdatedAt }).ExecuteCommandAsync();

            return true;
        });
    }
    public async Task<JournalPageV2Output> DetailAsync(long id)
    {
        var output = await Queryable()
           //.LeftJoin<DotMatrixPage>((a, b) => a.DotMatrixPageId == b.Id)
           .Where(a => a.Id == id)
           .Select(a => new JournalPageV2Output
           {
               JournalId = a.JournalId,
               JournalCatalogId = a.JournalCatalogId,
               JournalPageId = a.Id,
               Url = a.Url,
               Layout = a.Layout,
               PageNum = a.PageNum,
           })
           .FirstAsync();

        if (output != null)
        {
            var tasks = await JournalPageTaskRepository.Queryable()
                .Where(a => a.JournalPageId == output.JournalPageId)
                .ToListAsync();

            if (tasks.Count > 0)
            {
                var taskIds = tasks.Select(t => t.Id).ToList();
                var allAnswers = await JournalPageTaskAnswerRepository.Queryable()
                    .Where(a => taskIds.Contains(a.JournalPageTaskId))
                    .ToListAsync();

                output.Tasks = tasks.Select(t => new JournalPageTaskV2Output
                {
                    Id = t.Id,
                    GroupId = t.GroupId,
                    No = t.No,
                    Type = t.Type,
                    Answers = allAnswers
                        .Where(a => a.JournalPageTaskId == t.Id)
                        .Select(a => new JournalTaskAnswerOutput
                        {
                            Id = a.Id,
                            Answer = a.Answer,
                            AnswerUrl = a.AnswerUrL
                        }).ToList()
                }).ToList();
            }
        }
        //if (output?.Areas != null)
        //    output.Areas = await _JournalPageOtherRepository.Queryable().Where(w => w.JournalPageId == output.JournalPageId).Select<JournalPageOtherOutput>().ToListAsync();

        return output;
    }

    public async Task<bool> DeleteAsync(long id)
    {
        return await Deleteable().Where(d => d.Id == id).ExecuteCommandAsync() > 0;
    }
    //public async Task<List<JournalPageNoArticleOutput>> PageNoArticleAsync(long JournalId)
    //{
    //    return await Queryable().Where(d => d.JournalId == JournalId)
    //        .Where(w => w.JournalArticleId == null)
    //        .ToListAsync(x => new JournalPageNoArticleOutput()
    //        {
    //            Id = x.Id,
    //            PageUrl = x.Url,
    //            PageNum = x.PageNum
    //        });
    //}

    private int MillimeterToDotMatrixUnit(float millimeterValue)
    {
        return (int)(millimeterValue * 8 / 0.3);
    }
}

public class JournalDotPage_Task
{
    public int X { get; set; }
    public int Y { get; set; }
    public int W { get; set; }
    public int H { get; set; }
}

public class JournalDotPage_Answer
{
    public int X { get; set; }
    public int Y { get; set; }
    public int W { get; set; }
    public int H { get; set; }
}

public class JournalDotPage_Area
{
    public JournalDotPage_Task Task { get; set; }

    public List<JournalDotPage_Answer> AnswerList { get; set; }

    public long TaskId { get; set; }

}
