using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Performance.Services.ExtractExcelService
{
    public class ExtractJobService : IAutoInjection
    {
        private readonly ILogger logger;
        private readonly IHostingEnvironment env;
        private readonly AllotService allotService;
        private readonly ConfigService configService;
        private readonly DictionaryService dictionaryService;
        private readonly QueryService queryService;
        private readonly ExtractService extractService;
        private readonly PerforUserRepository userRepository;
        private readonly PerforHospitalRepository hospitalRepository;
        private readonly PerforPerallotRepository perallotRepository;

        public ExtractJobService(
            ILogger<ExtractJobService> logger,
            IHostingEnvironment env,
            AllotService allotService,
            ConfigService configService,
            DictionaryService dictionaryService,
            QueryService queryService,
            ExtractService extractService,
            PerforUserRepository userRepository,
            PerforHospitalRepository hospitalRepository,
            PerforPerallotRepository perallotRepository
            )
        {
            this.logger = logger;
            this.env = env;
            this.allotService = allotService;
            this.configService = configService;
            this.dictionaryService = dictionaryService;
            this.queryService = queryService;
            this.extractService = extractService;
            this.userRepository = userRepository;
            this.hospitalRepository = hospitalRepository;
            this.perallotRepository = perallotRepository;
        }

        public void Execute()
        {
            logger.LogInformation($"Initial ExtractJobService start at {DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")};");

            var hospitals = hospitalRepository.GetEntities(w => w.IsOpenTimedTasks == 1);
            if (hospitals == null || !hospitals.Any()) return;

            var userId = userRepository.GetEntity(t => t.Login.ToLower() == "admin" && t.States == 1 && t.IsDelete == 1)?.ID ?? 1;

            var date = DateTime.Now;
            var allots = perallotRepository.GetEntities(t => hospitals.Select(w => w.ID).Contains(t.HospitalId) && t.Year == date.Year && t.Month == date.Month);
            foreach (var hospital in hospitals)
            {
                try
                {
                    var allot = allots?.FirstOrDefault(t => t.HospitalId == hospital.ID);
                    if (allot == null)
                    {
                        allot = allotService.InsertAllot(new AllotRequest
                        {
                            HospitalId = hospital.ID,
                            Year = date.Year,
                            Month = date.Month
                        }, userId);
                        configService.Copy(allot);
                    }

                    if (allot == null || allot.ID == 0) continue;

                    var dict = new Dictionary<ExDataDict, object>();

                    var isSingle = hospital.IsSingleProject == 1;
                    dictionaryService.Handler(hospital.ID, allot, "", isSingle);
                    var data = queryService.Handler(hospital.ID, allot, "", isSingle, ref dict);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                }
            }

            logger.LogInformation($"Initial ExtractJobService end at {DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")};");
        }

        public void ExportFile()
        {
            logger.LogInformation($"Initial Extract ImportFile Generate start at {DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")};");

            var hospitals = hospitalRepository.GetEntities(w => w.IsOpenTimedTasks == 1);
            if (hospitals == null || !hospitals.Any()) return;

            var userId = userRepository.GetEntity(t => t.Login.ToLower() == "admin" && t.States == 1 && t.IsDelete == 1)?.ID ?? 1;

            var date = DateTime.Now;
            var allots = perallotRepository.GetEntities(t => hospitals.Select(w => w.ID).Contains(t.HospitalId));
            foreach (var hospital in hospitals)
            {
                try
                {
                    var allot = allots?.FirstOrDefault(t => t.HospitalId == hospital.ID && t.Year == date.Year && t.Month == date.Month);
                    if (allot == null)
                    {
                        allot = allotService.InsertAllot(new AllotRequest
                        {
                            HospitalId = hospital.ID,
                            Year = date.Year,
                            Month = date.Month
                        }, userId);
                        configService.Copy(allot);
                    }

                    if (allot == null || allot.ID == 0) continue;

                    var dict = new Dictionary<ExDataDict, object>();

                    var isSingle = hospital.IsSingleProject == 1;
                    var prevAllot = allots?.Where(t => t.HospitalId == hospital.ID && new int[] { 6, 8 }.Contains(t.States)).OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
                    string filePath = prevAllot?.Path ?? "";
                    string extractFilePath = extractService.Main(allot.ID, allot.HospitalId, "", "User" + userId, filePath, isSingle);

                    if (string.IsNullOrEmpty(extractFilePath) || !FileHelper.IsExistFile(extractFilePath)) return;
                    ImportFile(allot, filePath);

                    allotService.Generate(allot);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                }
            }

            logger.LogInformation($"Initial Extract ImportFile Generate end at {DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")};");
        }

        private bool ImportFile(per_allot allot, string filePath)
        {
            var name = FileHelper.GetFileNameNoExtension(filePath) + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var ext = FileHelper.GetExtension(filePath);

            var dpath = Path.Combine(env.ContentRootPath, "Files", $"{allot.HospitalId}", $"{allot.Year}{allot.Month.ToString().PadLeft(2, '0')}");
            FileHelper.CreateDirectory(dpath);

            var path = Path.Combine(dpath, $"{name}{ext}");

            using (var stream = new FileStream(filePath, FileMode.OpenOrCreate))
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                if (!FileHelper.CreateFile(path, bytes)) return false;
                allot.Path = path;
                allot.States = (int)AllotStates.FileUploaded;
                allot.Remark = EnumHelper.GetDescription(AllotStates.FileUploaded);
                allot.UploadDate = DateTime.Now;
                allot.Generate = (int)AllotGenerate.Init;
                if (!allotService.Update(allot)) return false;
            }

            configService.Clear(allot.ID);
            return true;
        }
    }
}
