using System.Collections;
using System.Text.RegularExpressions;
using NetModular.DocX.Core;


namespace Infrastructure.Helpers;

public class WordHelper
{
    /// <summary>
    /// 导出word
    /// </summary>
    /// <param name="tempFilePath">模板路径</param>
    /// <param name="outPath">保存路径</param>
    /// <param name="data">数据</param>
    public static void Export(string tempFilePath, string outPath, Dictionary<string, object> data)
    {
        bool isrewrite = true; // true=覆盖已存在的同名文件,false则反之
        //if (!System.IO.Directory.Exists(outPath))
        //{
        //    System.IO.Directory.CreateDirectory(outPath);
        //}
        File.Copy(tempFilePath, outPath, isrewrite);
        //新建一个Word文档，加载Load的方法和Create使用一样。
        using (DocX document = DocX.Load(outPath))
        {
            ReplaceDoc(document, data); //普通文本替换
            ReplaceTable(document, data); //表格处理
            ReplaceList(document, data); //文本列表处理

            document.Save(); //保存
        }
    }

    private static void ReplaceDoc(DocX doc, Dictionary<string, object> data)
    {
        foreach (var item in doc.Paragraphs)
        {
            ReplaceParagraph(item, data);
        }
    }

    private static void ReplaceList(DocX doc, Dictionary<string, object> data)
    {
        //一定要在 普通文本替换和表格处理之后
        foreach (var p in doc.Paragraphs)
        {
            var li = GetListInfo(p, data);
            if (li.IsList)
            {
                var pc = li.PTemp;
                for (int i = 0; i < li.Data.Count; i++)
                {
                    var pt = pc.InsertParagraphAfterSelf(p);
                    if (li.IsDict)
                    {
                        pc = ReplaceParagraph(pt, (Dictionary<string, object>)li.Data[i]);
                    }
                    else
                    {
                        pc = ReplaceParagraph(pt, li.Data[i]);
                    }
                }

                //删除模板行
                li.PTemp.Remove(false);
            }
            else
            {
                //do nonthing
            }
        }
    }

    private static void ReplaceTable(DocX doc, Dictionary<string, object> data)
    {
        var tbs = doc.Tables;
        foreach (var table in tbs)
        {
            //需要先判断表格是列表还是表单
            var ti = GetTableInfo(table, data);
            if (ti.IsList)
            {
                for (int i = 0; i < ti.Data.Count; i++)
                {
                    var rt = table.InsertRow(ti.RowTemp);
                    rt.Height = ti.RowTemp.Height;
                    rt.MinHeight = ti.RowTemp.MinHeight;
                    if (ti.IsDict)
                    {
                        ReplaceRow(rt, (Dictionary<string, object>)ti.Data[i]);
                    }
                    else
                    {
                        ReplaceRow(rt, ti.Data[i]);
                    }
                }

                //删除模板行
                ti.RowTemp.Remove();
            }
            else
            {
                //do nonthing
            }
        }
    }

    private static void ReplaceRow(Row row, Dictionary<string, object> data)
    {
        foreach (var cell in row.Cells)
        {
            foreach (var item in cell.Paragraphs)
            {
                ReplaceParagraph(item, data);
            }
        }
    }

    private static void ReplaceRow(Row row, object data)
    {
        foreach (var cell in row.Cells)
        {
            foreach (var item in cell.Paragraphs)
            {
                ReplaceParagraph(item, data);
            }
        }
    }

    private static Paragraph ReplaceParagraph(Paragraph p, Dictionary<string, object> data)
    {
        Paragraph pr = p;
        var ms = GetMatches(p.Text);
        var ks = new List<string>();
        var rs = new List<string>();
        foreach (Match m in ms)
        {
            if (m.Groups.Count > 1)
            {
                string text = m.Groups[1].Value;
                if (text.Contains("."))
                {
                    var ts = text.Split(".");
                    text = ts[ts.Length - 1];
                }

                ks.Add(text);
                rs.Add(m.Value);
            }
        }

        bool isCt = data.Any(op => ks.Any(o => o.Contains(op.Key)));
        bool isReplace = false;

        if (isCt)
        {
            if (ks.Count > 1)
            {
                for (int i = 0; i < ks.Count; i++)
                {
                    if (data.ContainsKey(ks[i]))
                    {
                        p.ReplaceText(rs[i], data[ks[i]]?.ToString());
                    }
                }
            }
            else if (ks.Count == 1)
            {
                string text = ks[0];
                if (data.ContainsKey(text))
                {
                    var ct = data[text]?.ToString();
                    var cts = ResolveText(ct);
                    var pc = p;
                    foreach (var item2 in cts)
                    {
                        if (string.IsNullOrWhiteSpace(item2)) continue;
                        var pt = pc.InsertParagraphAfterSelf(p);
                        pt.ReplaceText(rs[0], item2);
                        pc = pt;
                        pr = pc;
                    }

                    isReplace = true;
                }
            }

            if (isReplace)
            {
                //删除原来段落
                p.Remove(false);
            }
        }

        return pr;
    }

    private static Paragraph ReplaceParagraph(Paragraph p, object data)
    {
        var ms = GetMatches(p.Text);
        var isReplace = false;
        Paragraph pr = p;
        foreach (Match item1 in ms)
        {
            if (item1.Groups.Count > 1)
            {
                string text = item1.Groups[1].Value;

                var ct = data?.ToString();
                var cts = ResolveText(ct);
                var pc = p;
                foreach (var item2 in cts)
                {
                    var pt = pc.InsertParagraphAfterSelf(p);
                    pt.ReplaceText(item1.Value, item2);
                    pc = pt;
                    pr = pc;
                }

                isReplace = true;
            }
        }

        if (isReplace)
        {
            //删除原来段落
            p.Remove(false);
        }

        return pr;
    }

    private static IList<string> ResolveText(string text)
    {
        if (string.IsNullOrEmpty(text)) return new List<string>();
        text = text.Replace("\r\n", "\n").Replace("\r", "\n");
        return text.Split('\n');
    }

    private static MatchCollection GetMatches(string text)
    {
        if (string.IsNullOrEmpty(text)) text = "";
        Regex regex = new Regex("[#|\\$]([a-zA-Z0-9_.]+?)[#|\\$]",
            RegexOptions.IgnoreCase | RegexOptions.Multiline);
        return regex.Matches(text);
    }

    /// <summary>
    /// 只获取列表匹配项
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    private static MatchCollection GetListMatches(string text)
    {
        if (string.IsNullOrEmpty(text)) text = "";
        Regex regex = new Regex("\\$([a-zA-Z0-9_.]+?)\\$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
        return regex.Matches(text);
    }

    //纯辅助方法
    private class TableInfo
    {
        public bool IsList { get; set; }
        public bool IsDict { get; set; }
        public Row RowTemp { get; set; }
        public IList<object> Data { get; set; }
    }

    //判断表格是列表还是表单
    private static TableInfo GetTableInfo(Table table, Dictionary<string, object> data)
    {
        TableInfo result = new TableInfo();
        var r0 = table.Rows[table.Rows.Count - 1];
        var c0 = r0.Cells[r0.Cells.Count - 1];
        var ct = c0.Paragraphs[0].Text;
        var ms = GetListMatches(ct);
        foreach (Match item in ms)
        {
            if (item.Groups.Count > 1)
            {
                string text = item.Groups[1].Value;
                if (text.Contains("."))
                {
                    result.IsDict = true;
                    text = text.Split('.')[0];
                }

                if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表
                {
                    result.RowTemp = r0;
                    result.IsList = true;
                    result.Data = new List<object>();
                    foreach (var item1 in (data[text] as IList))
                    {
                        result.Data.Add(item1);
                    }

                    break;
                }
            }
        }

        return result;
    }

    private class ListInfo
    {
        public bool IsList { get; set; }
        public bool IsDict { get; set; }
        public Paragraph PTemp { get; set; }
        public IList<object> Data { get; set; }
    }

    private static ListInfo GetListInfo(Paragraph p, Dictionary<string, object> data)
    {
        ListInfo result = new ListInfo();
        var ms = GetListMatches(p.Text);
        foreach (Match item in ms)
        {
            if (item.Groups.Count > 1)
            {
                string text = item.Groups[1].Value;
                if (text.Contains("."))
                {
                    result.IsDict = true;
                    text = text.Split('.')[0];
                }

                if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表
                {
                    result.PTemp = p;
                    result.IsList = true;
                    result.Data = new List<object>();
                    foreach (var item1 in (data[text] as IList))
                    {
                        result.Data.Add(item1);
                    }

                    break;
                }
            }
        }

        return result;
    }
}