using Sugar.Enties;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using ServiceReference1;
using System.Data;
using System.IO;
using iTextSharp.text.pdf;
using WebAPIBase.Utils;
using iTextSharp.text;
using Sugar;
using SqlSugar;

/// <summary>
/// 流程审核生成pdf帮助类
/// </summary>
public class WorkFlowPDFHelper
{
    private static string webserviceUrl = "http://127.0.0.1/WorkFlowWebService60NodeJS/query.asmx";
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    /// <summary>
    /// pdf文件存放路径
    /// </summary>
    public static string pdfDirectory
    {
        get
        {
            return RequestHelper.IsRemote ? AppSettingsHelper.Configuration["ServiceVirtualPath:RealPath"] : AppSettingsHelper.Configuration["LocalVirtualPath:RealPath"];
        }
    }


    /// <summary>
    /// 创建webservice实例
    /// </summary>
    /// <returns></returns>
    public static QuerySoap Services()
    {
        //创建 HTTP 绑定对象
        var binding = new BasicHttpBinding();
        binding.SendTimeout = new TimeSpan(0, 5, 0);
        binding.ReceiveTimeout = new TimeSpan(0, 5, 0);
        //根据 WebService 的 URL 构建终端点对象，参数是提供的WebService地址
        var endpoint = new EndpointAddress(webserviceUrl);
        //创建调用接口的工厂，注意这里泛型只能传入接口 泛型接口里面的参数是WebService里面定义的类名+Soap
        var factory = new ChannelFactory<QuerySoap>(binding, endpoint);
        //从工厂获取具体的调用实例
        var callClient = factory.CreateChannel();
        return callClient;
    }
    /// <summary>
    /// 判断pdf文件夹是否存在
    /// </summary>
    /// <returns></returns>
    public static string CheckServerPdfFolder()
    {
        string WebServiceUrl = new ConfigItemValueManager().GetConfigItemValue("基础模块-流程管理-流程审批WebService地址");
        if (WebServiceUrl != "")
        {


            if (Services().PdfFileFolderCheck())
            {
                return WebServiceUrl;
            }

            else
                return "";
        }
        return "";
    }
    /// <summary>
    /// 检查pdf文件是否能存在
    /// </summary>
    /// <param name="filename"></param>
    /// <returns></returns>
    public static bool CheckServerPdfFileExists(string filename)
    {
        string WebServiceUrl = CheckServerPdfFolder();
        if (WebServiceUrl != "")
        {
            return Services().PdfFileExistsCheck(filename);
        }
        return false;
    }
    /// <summary>
    /// 建立pdf文件
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="fileName"></param>
    public static void CreatePDFForm(DataSet ds, string fileName)
    {
        FileStream fs = null;
        try
        {
            #region --生成pdf文件--
            if (ds == null)
            {
                return;
            }
            //新建文件，大小尺寸
            //iTextSharp.text.Rectangle singleFormSize = new iTextSharp.text.Rectangle(166.32F, 350.64F);
            int maxColumnNum = 0;
            for (int i = 1; i < ds.Tables.Count; i++)
            {
                if (maxColumnNum < ds.Tables[i].Columns.Count)
                    maxColumnNum = ds.Tables[i].Columns.Count;
            }
            iTextSharp.text.Document doc = new iTextSharp.text.Document();
            doc.SetMargins(5f, 5f, 5f, 5f);
            if (maxColumnNum > 5)
            {
                doc.SetPageSize(iTextSharp.text.PageSize.A4);
            }
            else
            {
                doc.SetPageSize(iTextSharp.text.PageSize.A6);
            }

            #region --字体--
            iTextSharp.text.pdf.BaseFont bfChinese = iTextSharp.text.pdf.BaseFont.CreateFont("C:\\WINDOWS\\Fonts\\simsun.ttc,1", iTextSharp.text.pdf.BaseFont.IDENTITY_H, iTextSharp.text.pdf.BaseFont.NOT_EMBEDDED);
            //iTextSharp.text.Font fontChinese = new iTextSharp.text.Font(bfChinese, 12, iTextSharp.text.Font.NORMAL, iTextSharp.text.Color.BLACK);
            //主表表单字体
            iTextSharp.text.Font fontChinese = new iTextSharp.text.Font(bfChinese, 12, iTextSharp.text.Font.NORMAL, iTextSharp.text.BaseColor.Black);
            //明细表字体
            iTextSharp.text.Font fontDetail = new iTextSharp.text.Font(bfChinese, 10, iTextSharp.text.Font.NORMAL, iTextSharp.text.BaseColor.Black);
            #endregion

            //保存文件

            if (!Directory.Exists(pdfDirectory))
            {
                Directory.CreateDirectory(pdfDirectory);
            }
            string filePath = $"{pdfDirectory}\\{fileName}.pdf";
            logger.Info($"【CreatePDFForm】filePath:{filePath}");

            fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
            fs.SetLength(0);

            /*
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }               
            fs = new FileStream(filePath, FileMode.Create);
             * */
            PdfWriter writer = PdfWriter.GetInstance(doc, fs);

            //打开文件
            doc.Open();

            #region --画表格--
            if (ds.Tables.Count > 0)
            {

                iTextSharp.text.Paragraph pTitle = new iTextSharp.text.Paragraph(new iTextSharp.text.Chunk(ds.DataSetName, fontChinese));

                pTitle.SetAlignment("center");
                doc.Add(pTitle);

                #region --主表--
                DataTable dtMain = ds.Tables[0];

                //主表样式
                iTextSharp.text.Table tblMain = new iTextSharp.text.Table(2);
                tblMain.BorderWidth = 1;
                tblMain.BorderColor = new iTextSharp.text.BaseColor(0, 0, 0);
                tblMain.Cellpadding = 1;
                tblMain.Cellspacing = 1;
                tblMain.Width = 100;
                tblMain.SetWidths(new int[] { 35, 65 });
                //主表内容
                foreach (DataColumn cc in dtMain.Columns)
                {
                    string[] cellTitle = cc.ColumnName.Split('$');

                    tblMain.AddCell(new iTextSharp.text.Cell(new iTextSharp.text.Phrase(cellTitle[0], fontChinese)));
                    iTextSharp.text.Cell cellValue = new iTextSharp.text.Cell(new iTextSharp.text.Phrase(dtMain.Rows[0][cc.ColumnName].SConvertString(), fontChinese));
                    if (cellTitle.Length > 1)
                    {
                        cellValue.Colspan = Convert.ToInt16(cellTitle[1]);
                    }
                    tblMain.AddCell(cellValue);
                }
                //写入文件
                doc.Add(tblMain);

                #endregion

                #region --明细表--
                for (int i = 1; i < ds.Tables.Count; i++)
                {
                    DataTable dtDetail = ds.Tables[i];
                    //明细表名称
                    doc.Add(new iTextSharp.text.Paragraph(dtDetail.TableName, fontChinese));

                    //明细表样式
                    iTextSharp.text.Table tblDetail = new iTextSharp.text.Table(dtDetail.Columns.Count);
                    tblDetail.BorderWidth = 1;
                    tblDetail.BorderColor = new iTextSharp.text.BaseColor(0, 0, 0);
                    tblDetail.Cellpadding = 1;
                    tblDetail.Cellspacing = 1;
                    tblDetail.Width = 100;
                    //表头
                    foreach (DataColumn cc in dtDetail.Columns)
                    {
                        tblDetail.AddCell(new iTextSharp.text.Cell(new iTextSharp.text.Phrase(cc.ColumnName, fontDetail)));
                    }
                    //数据行
                    foreach (DataRow dr in dtDetail.Rows)
                    {
                        foreach (DataColumn cc in dtDetail.Columns)
                        {
                            iTextSharp.text.Cell cellValue = new iTextSharp.text.Cell(new iTextSharp.text.Phrase(dr[cc.ColumnName].SConvertString(), fontDetail));
                            cellValue.SetHorizontalAlignment("right");
                            cellValue.SetVerticalAlignment("bottom");
                            tblDetail.AddCell(cellValue);
                        }
                    }
                    //写入文件
                    doc.Add(tblDetail);
                }
                #endregion


            }
            else
            {
                doc.Add(new iTextSharp.text.Paragraph("对不起，没有取到数据", fontChinese));

            }
            #endregion

            //关闭文件
            doc.Close();
            writer.Close();
            fs.Close();
            fs.Dispose();
            #endregion


            string WebServiceUrl = CheckServerPdfFolder();
            if (WebServiceUrl != "")
            {
                //将pdf 文件写入database
                WorkFlowPDFFileService pdffileService = new WorkFlowPDFFileService();
                pdffileService.Save("WorkFlowCase", fileName, "");

                //将database中的pdf文件写入webservice服务器  异步调用接口
                logger.Info($"【复制文件到服务器 PdfFileCopy】fileName:{fileName}");
                Services().PdfFileCopyAsync(fileName, "WorkFlowCase");
                //logger.Info($"【复制文件到服务器 PdfFileCopy】copy:{copy}");

                //处理附件
                new WorkFlowAttachRule().ConvertFileToAttachment(fileName, WebServiceUrl);
            }
        }
        catch (Exception ex)
        {
            //logger.Error(ex);
            throw new ApplicationException("CreatePDFForm错误：" + ex.Message);
        }

    }

    /// <summary>
    /// 删除pdf文件
    /// </summary>
    /// <param name="fileName"></param>
    public static void DeleteFile(string fileName)
    {
        try
        {
            string filePath = $"{pdfDirectory}\\{fileName}.pdf";
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }

            //在database中标记要删除的pdf文件
            WorkFlowPDFFileService pdffileService = new WorkFlowPDFFileService();
            pdffileService.MarkDelete("WorkFlowCase", fileName);
            //删除服务器上的pdf文件，删除database中的pdf文件记录

            string WebServiceUrl = CheckServerPdfFolder();
            if (WebServiceUrl != "")
            {
                Services().PdfFileRemoveAsync(fileName, "WorkFlowCase");
                Services().PdfFileRemoveAsync(fileName, "CaseCode");
            }
        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-DeleteFile错误：" + ex.Message);
        }

    }


    /// <summary>
    /// 填充dt主表单
    /// </summary>
    /// <param name="dt"></param>
    /// <param name="columnCaption"></param>
    /// <param name="rowValue"></param>
    public static void FillMainFormData(DataTable dt, string columnCaption, string rowValue)
    {
        dt.Columns.Add(columnCaption);
        if (dt.Rows.Count == 0)
        {
            dt.Rows.Add(dt.NewRow());
        }
        dt.Rows[0][columnCaption] = rowValue;
    }


}


public class WorkFlowAttachRule : WorkFlowProcedureManager
{
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    public WorkFlowAttachRule()
    {
        //
        // TODO: 在此处添加构造函数逻辑
        //
    }
    public static bool CheckServerPdfFolder(string casecode)
    {
        string WebServiceUrl = WorkFlowPDFHelper.CheckServerPdfFolder();
        if (WebServiceUrl != "")
        {
            if (WorkFlowPDFHelper.Services().AttachFileExistsCheck(casecode))
                return true;
        }
        return false;
    }
    /// <summary>
    /// 把附件存在数据库中
    /// </summary>
    /// <param name="attachmenttype"></param>
    /// <param name="mastercode"></param>        
    public void ConvertFileToAttachment(string casecode, string WebServiceUrl)
    {
        try
        {
            //todo:删除服务器上的附件文件
            // ../workflow/@casecode/
            WorkFlowPDFHelper.Services().PdfFileRemoveAsync(casecode, "CaseCode");

            //清空workflowpdffile 

            string sqlDelete = $"delete from workflowpdffile where attachmenttype='WorkFlowActOpinion'and CaseCode='{casecode}'";
            logger.Info($"【ConvertFileToAttachment】sqlDelete:{sqlDelete}");
            Db.Ado.ExecuteCommand(sqlDelete);

            //从附件表attachment中写入附件到workflowpdffile
            string sqlAllAttachment = $@"select * from attachment where attachmenttype='WorkFlowActOpinion' and MasterCode in
    (select ApplicationCode from WorkFlowOpinion where CaseCode='{casecode}')
    and (right(filename,4) in('.doc','.xls','.ppt','.pdf','.log','.txt','.htm','.mp3','.mp4','.jpg','.gif','.png','.bmp')
    or right(filename,5) in('.docx','.xlsx','.pptx','.html','.jgep','.jpeg'))";
            logger.Info($"【ConvertFileToAttachment】sqlAllAttachment:{sqlAllAttachment}");
            DataTable dtAttachment = Db.Ado.GetDataTable(sqlAllAttachment);
            logger.Info($"【ConvertFileToAttachment】dtAttachment.count:{dtAttachment.Rows.Count}");
            if (dtAttachment.Rows.Count > 0)
            {

                WorkFlowPDFFileService pdfService = new WorkFlowPDFFileService();
                foreach (DataRow dr in dtAttachment.Rows)
                {
                    //写入文件
                    pdfService.SaveAttachment(dr, casecode);
                }
            }
            //业务单据的附件
            string sqlFormAttachment = $@"select at.* from attachment at inner join( 
select b.AttachmentType,a.ApplicationCode,a.casecode from WorkFlowCase a 
    inner join WorkFlowAttachmentType b on a.ApplicationPath=b.ApplicationPath  where a.CaseCode='{casecode}'
) as wk on at.AttachmentType=wk.AttachmentType and at.MasterCode=wk.ApplicationCode 
where (right(filename,4) in('.doc','.xls','.ppt','.pdf','.log','.txt','.htm','.mp3','.mp4','.jpg','.gif','.png','.bmp')
    or right(filename,5) in('.docx','.xlsx','.pptx','.html','.jgep','.jpeg'))";
            logger.Info($"【ConvertFileToAttachment】sqlFormAttachment:{sqlFormAttachment}");
            DataTable dtFormAttachment = Db.Ado.GetDataTable(sqlFormAttachment);
            if (dtFormAttachment.Rows.Count > 0)
            {

                WorkFlowPDFFileService pdfService = new WorkFlowPDFFileService();
                foreach (DataRow dr in dtFormAttachment.Rows)
                {
                    //写入文件
                    pdfService.SaveAttachment(dr, casecode);
                }
            }

            //复制文件
            WorkFlowPDFHelper.Services().PdfFileCopyAsync(casecode, "CaseCode");
        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-ConvertFileToAttachment错误：" + ex.Message);
        }
    }
}

#region --WorkFlowPDFFileService
/// <summary>
/// 
/// </summary>
public class WorkFlowPDFFileService : WorkFlowProcedureManager
{
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    public WorkFlowPDFFileService()
    {
        //
        // TODO: 在此处添加构造函数逻辑
        //
    }

    public DataTable GetByMasterCodeAttachmentType(string attachmenttype, string mastercode)
    {
        try
        {
            string sql = $"select * from WorkFlowPDFFile where attachmenttype='{attachmenttype}' and mastercode='{mastercode}'";
            ;
            DataTable dt = Db.Ado.GetDataTable(sql);
            return dt;
        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-GetByMasterCodeAttachmentType错误：" + ex.Message);
        }
    }
    /// <summary>
    ///  保存流程表单pdf文件
    /// </summary>
    /// <param name="attachmenttype"></param>
    /// <param name="mastercode"></param>
    /// <param name="usercode"></param>
    public void Save(string attachmenttype, string mastercode, string usercode)
    {
        try
        {
            string filename = string.Format("{0}.pdf", mastercode);
            string fullname = $"{WorkFlowPDFHelper.pdfDirectory}\\{filename}";

            FileInfo fi = new FileInfo(fullname);

            if (fi.Exists)
            {
                byte[] content = new byte[fi.Length];
                FileStream fs = fi.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                fs.Read(content, 0, (int)fi.Length);

                fs.Close();
                fs.Dispose();

                string sql = $"select 1 from WorkFlowPDFFile where attachmenttype='{attachmenttype}' and mastercode='{mastercode}'";
                if (Db.Ado.GetString(sql).IsNotNullAndEmpty())
                {
                    //删除旧pdf文件记录
                    Db.Ado.ExecuteCommand($"delete from WorkFlowPDFFile where attachmenttype='{attachmenttype}' and mastercode='{mastercode}'");
                }

                var pdfFile = new WorkFlowPDFFile();
                pdfFile.AttachMentType = attachmenttype;
                pdfFile.MasterCode = mastercode;
                pdfFile.Content_Type = "application/pdf";
                pdfFile.Length = (int)fi.Length;
                pdfFile.FileName = filename;
                pdfFile.CreatePerson = "";
                pdfFile.CreateDate = DateTime.Now;
                pdfFile.Content = content;

                logger.Info($"【保存pdf附件】attachmenttype:{attachmenttype},mastercode:{mastercode}");
                var row = Db.Insertable(pdfFile).ExecuteCommand();
                logger.Info($"【保存pdf附件】执行成功row:{row}");
            }







        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-Save错误：" + ex.Message);
        }
    }

    public void MarkDelete(string attachmenttype, string mastercode)
    {
        try
        {
            string sql = @"update WorkFlowPDFFile 
                        set attachmenttype='---'+attachmenttype
                        where (attachmenttype='{attachmenttype}' and mastercode='{mastercode}') or (attachmenttype='WorkFlowActOpinion'and CaseCode='{mastercode}')";
            Db.Ado.ExecuteCommand(sql);

        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-MarkDelete错误：" + ex.Message);
        }

    }

    /// <summary>
    /// 保存流程附件文件
    /// </summary>
    /// <param name="dr"></param>
    /// <param name="casecode"></param>
    public void SaveAttachment(DataRow dr, string casecode)
    {
        try
        {
            var entity = new WorkFlowPDFFile();
            entity.AttachMentType = dr["attachmenttype"].SConvertString();
            entity.MasterCode = dr["mastercode"].SConvertString();
            entity.FileName = dr["filename"].SConvertString();
            entity.Content_Type = dr["content_type"].SConvertString();
            entity.CreatePerson = dr["createperson"].SConvertString();
            entity.CaseCode = casecode;


            bool isAdd = true;
            if (dr["Content"] != DBNull.Value)
            {
                entity.Content = (byte[])dr["Content"];
                entity.Length = dr["length"].ToInteger();

            }
            else
            {
                //存文件的
                string guidname = ConvertRule.ToString(dr["GuidName"]);
                string fullname = GetFileName(guidname, ConvertRule.ToDateString(dr["CreateDate"]));
                FileInfo fi = new FileInfo(fullname);
                if (fi.Exists)
                {
                    byte[] content = new byte[fi.Length];
                    FileStream fs = fi.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    fs.Read(content, 0, (int)fi.Length);

                    entity.Content = content;
                    entity.Length = (int)fi.Length;


                    fs.Close();
                    fs.Dispose();

                }
                else
                {
                    isAdd = !isAdd;
                }

            }
            if (isAdd)
            {
                Db.Insertable(entity).ExecuteCommand();
            }
        }
        catch (Exception ex)
        {
            throw new ApplicationException("WorkFlowPDFHelper-SaveAttachment错误：" + ex.Message);
        }

    }

    #region--private方法--
    /// <summary>
    /// 替换文件名中的非法字符为同样式的其他字符
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    private static string ReplaceFileName(string name)
    {
        name = name.Replace("/", "／");
        name = name.Replace("\\", "＼");
        name = name.Replace(":", "：");
        name = name.Replace("*", "※");
        name = name.Replace("?", "？");
        name = name.Replace("\"", "“");
        name = name.Replace("<", "＜");
        name = name.Replace(">", "＞");
        name = name.Replace("|", "│");
        return name;
    }
    private string GetPath(string date)
    {
        new DocumentRule().Init();
        string fullname;
        string _Path = new ConfigItemValueManager().GetConfigItemValue("基础模块-附件存储设置-文件存储目录").ToLower();
        switch (DocumentRule._SavePathMode)
        {
            case AttachmentSavePathMode.ROOT:
                fullname = _Path;
                break;
            case AttachmentSavePathMode.YYYY:
                fullname = Path.Combine(_Path, GetYearString(date));
                break;
            case AttachmentSavePathMode.YYYYMM:
                fullname = Path.Combine(_Path, GetYearMonthString(date));
                break;
            case AttachmentSavePathMode.YYYYMMDD:
                fullname = Path.Combine(_Path, GetYearMonthDateString(date));
                break;
            default:
                fullname = _Path;
                break;
        }
        return fullname;
    }
    private string GetFileName(string filename, string date)
    {
        return Path.Combine(GetPath(date), filename);
    }
    private static string GetYearString(string date)
    {
        DateTime dt = new DateTime();
        if (date == string.Empty) return string.Empty;
        if (DateTime.TryParse(date, out dt))
        {
            return dt.Year.ToString();
        }
        else
        {
            return string.Empty;
        }
    }
    private static string GetYearMonthString(string date)
    {
        DateTime dt = new DateTime();
        if (date == string.Empty) return string.Empty;
        if (DateTime.TryParse(date, out dt))
        {
            return dt.Year.ToString() + dt.Month.ToString().PadLeft(2, '0');
        }
        else
        {
            return string.Empty;
        }
    }
    private static string GetYearMonthDateString(string date)
    {
        DateTime dt = new DateTime();
        if (date == string.Empty) return string.Empty;
        if (DateTime.TryParse(date, out dt))
        {
            return dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString().PadLeft(2, '0');
        }
        else
        {
            return string.Empty;
        }
    }

    #endregion
}
#endregion
