using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.Infrastructure;
using Performance.Services;
using Performance.Services.Queues;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Performance.Api.Controllers
{
    [Route("api/extract")]
    public class ModExtractController : Controller
    {
        private readonly ClaimService _claim;
        private readonly AllotService _allotService;
        private readonly CustomExtractService _extractService;
        private readonly IServiceScopeFactory _serviceScopeFactory;
        private readonly IHubNotificationQueue _notificationQueue;
        private readonly IBackgroundTaskQueue _backgroundTaskQueue;

        public ModExtractController(
            ClaimService claim,
            AllotService allotService,
            CustomExtractService extractService,
            IServiceScopeFactory serviceScopeFactory,
            IHubNotificationQueue notificationQueue,
            IBackgroundTaskQueue backgroundTaskQueue)
        {
            _claim = claim;
            _allotService = allotService;
            _extractService = extractService;
            _serviceScopeFactory = serviceScopeFactory;
            _notificationQueue = notificationQueue;
            _backgroundTaskQueue = backgroundTaskQueue;
        }

        [HttpPost("custom/{allotId}")]
        public ApiResponse CustomExtract(int allotId)
        {
            var userId = _claim.GetUserId();
            if (!_extractService.CheckConfigScript(userId, allotId))
                return new ApiResponse(ResponseType.Fail, "配置信息错误");

            _backgroundTaskQueue.QueueBackgroundWorkItem(async token =>
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider.GetRequiredService<CustomExtractService>();
                    var scopedAllotService = scope.ServiceProvider.GetRequiredService<AllotService>();
                    var scopedQueue = scope.ServiceProvider.GetRequiredService<IHubNotificationQueue>();

                    if (scopedServices.ExtractData(userId, allotId, out string resultFilePath))
                    {
                        scopedAllotService.UpdateAllotCustomExtractPath(allotId, resultFilePath);
                        scopedQueue.Send(new Notification(allotId, "CustomDowoload", new CustomDownloadContent("自定义数据提取数据成功，是否立即下载", allotId)));
                    }
                    else
                    {
                        scopedQueue.Send(new Notification(allotId, "Notification", new TextContent("自定义数据提取数据失败", NotificationLevel.ERR)));
                    }

                    await Task.Delay(TimeSpan.FromSeconds(5), token);
                }
            });
            _notificationQueue.Send(new Notification(allotId, "Notification", new TextContent("自定义数据提取任务开始执行")));


            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 从WebAPI下载文件
        /// </summary>
        /// <returns></returns>
        [Route("down/{allotId}")]
        [HttpGet]
        [AllowAnonymous]
        public IActionResult DownFile(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (allot == null || string.IsNullOrWhiteSpace(allot.CustomExtractPath) || !FileHelper.IsExistFile(allot.CustomExtractPath))
            {
                return new ObjectResult(new ApiResponse(ResponseType.Fail, "文件不存在"));
            }

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(allot.CustomExtractPath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            string fileExt = Path.GetExtension(allot.CustomExtractPath);
            var provider = new FileExtensionContentTypeProvider();
            var memi = provider.Mappings[fileExt];
            return File(memoryStream, memi, Path.GetFileName(allot.CustomExtractPath));
        }
    }
}