using FluentScheduler;
using Newtonsoft.Json;
using Siger.ApiCommon.Utilities;
using Siger.ApiDashboard.Tasks;
using Siger.ApiDashboard.Tasks.Model;
using Siger.ApiDashboard.Tasks.Reports;
using Siger.DataSchedule.Infrastructure.Extend;
using Siger.Middlelayer.AccRepository;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.KpiRespository;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.QmsRepository;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.TpmRepository;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;

namespace Siger.Schedule.DashboardModule
{
    public class AutoMonthReportJobSchedule : IScheduleJob
    {
        AutoMonthReportJob andonHelper;
        public void PreInit(ScheduleContext context)
        {
            Logger.RegisterLogEngine(Module.Dashboard);
            andonHelper = new AutoMonthReportJob();
        }
        public void Execute(ScheduleContext context)
        {
            andonHelper.Execute();
        }


        public void AfterExecute(ScheduleContext context)
        {

        }


        public void Undo()
        {

        }
    }
    /// <summary>
    /// 月报自动推送任务
    /// </summary>
    public class AutoMonthReportJob 
    {
        private readonly MonthReportHelper _monthReport;
        public AutoMonthReportJob()
        {
            var qmsDbContext = new ApiQmsDbContext();
            var tpmDbContext = new ApiTpmDbContext();
            var apiDbContext = new ApiKpiDbContext();
            var confDbContext = new ApiConfigDbContext();
            var accDbContext = new ApiAccDbContext();
            _monthReport = new MonthReportHelper(qmsDbContext, tpmDbContext, apiDbContext, confDbContext, accDbContext);
        }

        public void Execute()
        {
            try
            {
                var configs = _monthReport.GetAllConfigs();
                foreach (var cfg in configs)
                {
                    ExecuteConvert(cfg);
                }
            }
            catch (Exception e)
            {
                Logger.WriteLineError($"AutoMonthReport Execute,{e}");
            }
        }

        private void ExecuteConvert(siger_project_monthreport_config config)
        {
            var emailConfig = _monthReport.GetEmailConfigs(config.project_id);
            if (emailConfig == null)
            {
                Logger.WriteLineError($"邮件服务器未配置,{config.project_id}");
                return;
            }
            var users = _monthReport.UserEmails(config.user_mids);
            if (!users.Any())
            {
                Logger.WriteLineError($"用户邮箱地址为空,{config.user_mids}");
                return;
            }
            try
            {
                var MainTemplate = new List<object>();
                var templates = _monthReport.GetRptTemplates(config.id);
                if (!templates.Any())
                    return;
                var timerange = _monthReport.TimeRange(config);
                foreach (var temp in templates)
                {
                    var templateID = (ReportTemplate)temp.template_id;
                    switch (templateID)
                    {
                        case ReportTemplate.MachineOEE:
                        case ReportTemplate.MachineSplit:
                        case ReportTemplate.MachineCrop:
                        case ReportTemplate.Productivity:
                        case ReportTemplate.MachineOfProductivity:
                        case ReportTemplate.MachineStateOfStop:
                            {
                                MainTemplate.Add("not support");
                                break;
                            }
                        case ReportTemplate.UtilizationComm:
                            {
                                var usageObj = MouduleUtilizationComm.GetResponseSum(_monthReport, config, temp, timerange);
                                MainTemplate.Add(usageObj);
                                break;
                            }
                    }
                }

                var strObj = JsonConvert.SerializeObject(MainTemplate);
                var result = new ReporterMain().GeneratePdf(config, strObj, timerange);
                if (result.Result == ReportSendResult.Successful)
                {
                    var url = config.send_type == 0 ? result.HtmlPath : result.PdfPath;
                    try
                    {
                        var body = config.remark.Replace("\n", "<br>");
                        MailHelper.SendMailForUsers(emailConfig.server, true, emailConfig.send, emailConfig.code,
                           emailConfig.send, emailConfig.send, users.Select(t => t.work_email).ToList(),
                           config.name, body, new List<string> { url });
                    }
                    catch (Exception e)
                    {
                        Logger.WriteLineError($"发送邮件失败,{e}");
                    }
                    _monthReport.AddSendRecord(config.id, string.Join(",", users.Select(t => t.name).ToList()), url);
                }
            }
            catch (Exception e)
            {
                Logger.WriteLineError("convert pdf failed, error:" + e);
            }
        }
    }

    /// <summary>
    /// 月报发送周期
    /// </summary>
    public enum MonthReportCycle
    {
        Day = 1,

        Week,

        Month
    }

    public enum ReportTemplate
    {
        [Description("主模板")]
        MainReport = 0,
        [Description("生产管理月报")]
        ProductionManagement = 1,

        [Description("效率分析月报")]
        EfficiencyAnalysis,

        [Description("综合月报")]
        Comprehensive,

        [Description("产量产出月报")]
        YieldReport,
        [Description("设备总体运行状况")] //新增
        MachineRunning = 5,
        [Description("设备报警分析")]
        MachineAlarm = 6,
        [Description("设备综合效率分析")]
        MachineOEE = 7,
        [Description("设备切片分析")]
        MachineSplit = 8,
        [Description("设备稼动率")]
        MachineCrop = 9,
        [Description("生产效率")]
        Productivity = 10,
        [Description("设备产出统计")]
        MachineOfProductivity = 11,
        [Description("停机状态产出统计")]
        MachineStateOfStop = 12,
        /// <summary>
        /// 系统使用率统计
        /// </summary>
        [Description("系统使用率统计")] //SKF
        UtilizationComm = 13
    }

    internal abstract class ReporBase
    {
        protected string OriginalContent { get; set; }

        protected string RootDir { get; set; }
        protected ReporBase()
        {
            var fileSetting = Config<FileSettings>.Get();
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.TemplateFileName);
            
            RootDir = rootDir;
        }
        /// <summary>
        /// 2.0 替换HTML
        /// </summary>
        /// <param name="config">表格</param>
        /// <param name="dataStr">图表数据</param>
        /// <param name="range"></param>
        protected abstract void ReplaceHtml(siger_project_monthreport_config config, string dataStr, TimeRange range);

        /// <summary>
        ///  2.0 转PDF
        /// </summary>
        /// <param name="config"></param>
        /// <param name="dataStr"></param>
        /// <param name="range"></param>
        /// <returns></returns>
        public abstract ConvertPdfResult GeneratePdf(siger_project_monthreport_config config, string dataStr, TimeRange range);
    }

    internal class ConvertPdfResult
    {
        public ReportSendResult Result { get; set; }

        public string PdfPath { get; set; }
        public string HtmlPath { get; set; }

        public ConvertPdfResult(ReportSendResult result, string pdfPath = "", string htmlPath = "")
        {
            Result = result;
            PdfPath = pdfPath;
            HtmlPath = htmlPath;
        }
    }

    internal enum ReportSendResult
    {
        [Description("Html模板文件未找到")]
        HtmlTemplateNotFound,

        [Description("读取Html模板文件失败")]
        ReadHtmlTemplateFailed,

        [Description("写入Html模板文件失败")]
        WriteHtmlTemplateFailed,

        [Description("生成数据出错")]
        GenerateDataError,

        [Description("转换Pdf出错")]
        ConvertPdfFailed,

        [Description("未找到收件人邮箱")]
        UserEmailNotFound,

        [Description("邮件发送失败")]
        EmailSendFailed,

        [Description("未知异常")]
        Unkown,

        [Description("成功")]
        Successful,
    }

    internal class ReporterMain : ReporBase
    {

        public ReporterMain()
        {
            var fileName = Path.Combine(RootDir, "cnc.New_Template.html");
            if (!File.Exists(fileName))
                throw new Exception("templates file not found.");

            OriginalContent = FileHelper.ReadFile(fileName);
            if (string.IsNullOrWhiteSpace(OriginalContent))
                throw new Exception("read template file failed.");
        }
        /// <summary>
        /// 转换文件
        /// </summary>
        /// <param name="config"></param>
        /// <param name="dataStr"></param>
        /// <param name="range"></param>
        /// <returns></returns>

        public override ConvertPdfResult GeneratePdf(siger_project_monthreport_config config, string dataStr, Middlelayer.Share.Models.TimeRange range)
        {
            ReplaceHtml(config, dataStr, range);
            return ConvertHelper.ConvertToPdf(OriginalContent, config.send_type);
        }

        protected override void ReplaceHtml(siger_project_monthreport_config config, string dataStr, Middlelayer.Share.Models.TimeRange range)
        {
            var timeRange = range.StartTime + " - " + range.EndTime;

            OriginalContent = OriginalContent.Replace("{title}", config.name);
            OriginalContent = OriginalContent.Replace("{timeRange}", timeRange);
            OriginalContent = OriginalContent.Replace("{dataArray}", dataStr);
        }
        internal class ConvertHelper
        {
            public static ConvertPdfResult ConvertToPdf(string htmlContent, siger_project_monthreport_config config)
            {
                //生成html再转pdf
                var newHtmlFolder = GetNewHtmlFolder();
                var newHtmlPath = Path.Combine(newHtmlFolder, GetNewHtmlFileName((ReportTemplate)config.template_id) + ".html");
                FileHelper.WriteFile(htmlContent, newHtmlPath);
                if (!File.Exists(newHtmlPath))
                {
                    return new ConvertPdfResult(ReportSendResult.WriteHtmlTemplateFailed);
                }

                //convert
                var pdfFilePath = ConvertPdf(newHtmlPath, (ReportTemplate)config.template_id);
                if (!File.Exists(pdfFilePath))
                {
                    return new ConvertPdfResult(ReportSendResult.ConvertPdfFailed);
                }

                //重命名
                var pdfFile = new FileInfo(pdfFilePath);
                var destPath = Path.Combine(pdfFile.DirectoryName, config.name + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf");
                //判断是否重名
                if (!File.Exists(destPath))
                {
                    pdfFile.CopyTo(destPath);
                }

                return new ConvertPdfResult(ReportSendResult.Successful, destPath);
            }
            public static ConvertPdfResult ConvertToPdf(string htmlContent, int sendType = 0)
            {
                //生成html再转pdf
                var reportTemplate = ReportTemplate.MainReport;
                var newHtmlFolder = GetNewHtmlFolder();
                var newHtmlPath = Path.Combine(newHtmlFolder, GetNewHtmlFileName(reportTemplate) + ".html");
                FileHelper.WriteFile(htmlContent, newHtmlPath);
                if (!File.Exists(newHtmlPath))
                    return new ConvertPdfResult(ReportSendResult.WriteHtmlTemplateFailed);

                if (sendType == 0)
                    return new ConvertPdfResult(ReportSendResult.Successful, "", newHtmlPath);

                //convert
                var pdfFilePath = ConvertPdf(newHtmlPath, reportTemplate);
                if (!File.Exists(pdfFilePath))
                    return new ConvertPdfResult(ReportSendResult.ConvertPdfFailed);

                //重命名
                var pdfFile = new FileInfo(pdfFilePath);
                var destPath = Path.Combine(pdfFile.DirectoryName, reportTemplate.ToString() + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf");
                //判断是否重名
                if (!File.Exists(destPath))
                    pdfFile.CopyTo(destPath);

                return new ConvertPdfResult(ReportSendResult.Successful, destPath, newHtmlPath);
            }
            private static string GetNewHtmlFolder()
            {
                var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "NewHtml",
                    DateTime.Now.ToString("yyyy-MM-dd"));

                return rootDir;
            }

            private static string GetNewHtmlFileName(ReportTemplate template)
            {
                var description = template.ToString();
                return description + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            }

            private static string ConvertPdf(string fileName, ReportTemplate template)
            {
                var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "PdfReport",
                    DateTime.Now.ToString("yyyy-MM-dd"));
               

                var path = Path.Combine(rootDir, GetNewHtmlFileName(template) + ".pdf");

                var arguments = " " + fileName + " " + path;

                string toolPath;

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows).Equals(true))
                {
                    toolPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Utilities", "wkhtmltopdf.exe");
                    if (!File.Exists(toolPath))
                    {
                        throw new FileNotFoundException("Can not find pdf convert tool.");
                    }
                }
                else
                {
                    toolPath = "wkhtmltopdf";
                }

                try
                {
                    var p = new Process
                    {
                        StartInfo =
                    {
                        FileName = toolPath,
                        Arguments = arguments,
                        UseShellExecute = false,
                        RedirectStandardInput = true,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        CreateNoWindow = false
                    }
                    };
                    p.Start();
                    p.WaitForExit();
                    System.Threading.Thread.Sleep(1000);
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("ConvertPdf Error," + e);
                    throw;
                }

                return path;
            }
        }
    }
}
