using System.Text.RegularExpressions;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using SolutionErp.Application.Forms.Services;

namespace SolutionErp.Infrastructure.Forms;

// Placeholder replace syntax: {{fieldName}}
// Hạn chế Phase 2 MVP:
//   - Không support {{#loop}}...{{/loop}} (table lặp) — Phase 2 iteration 2
//   - Không split placeholder giữa 2 <w:t> (Word hay làm) — merge runs trước khi replace
public class DocxRenderer
{
    private static readonly Regex PlaceholderRegex = new(@"\{\{([a-zA-Z0-9_\.]+)\}\}", RegexOptions.Compiled);

    public async Task<RenderResult> RenderAsync(
        string templateAbsolutePath,
        IReadOnlyDictionary<string, string?> data,
        string outputFileName,
        CancellationToken ct = default)
    {
        await Task.Yield();
        var bytes = File.ReadAllBytes(templateAbsolutePath);
        using var ms = new MemoryStream();
        ms.Write(bytes, 0, bytes.Length);
        ms.Position = 0;

        using (var doc = WordprocessingDocument.Open(ms, isEditable: true))
        {
            var mainPart = doc.MainDocumentPart
                ?? throw new InvalidOperationException("Template .docx không có MainDocumentPart");
            var document = mainPart.Document
                ?? throw new InvalidOperationException("Template .docx không có Document");
            var body = document.Body;
            if (body is null) throw new InvalidOperationException("Template .docx không có Body");

            // Xử lý cả main document + headers + footers
            ReplaceInElement(body, data);
            foreach (var hp in mainPart.HeaderParts)
                if (hp.Header is not null) ReplaceInElement(hp.Header, data);
            foreach (var fp in mainPart.FooterParts)
                if (fp.Footer is not null) ReplaceInElement(fp.Footer, data);

            document.Save();
        }

        return new RenderResult(
            ms.ToArray(),
            outputFileName,
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    }

    private static void ReplaceInElement(DocumentFormat.OpenXml.OpenXmlElement root, IReadOnlyDictionary<string, string?> data)
    {
        // Iterate từng paragraph: gom text của mọi <w:t> trong cùng paragraph → replace → gán lại vào <w:t> đầu + clear rest
        foreach (var para in root.Descendants<Paragraph>().ToList())
        {
            var textElements = para.Descendants<Text>().ToList();
            if (textElements.Count == 0) continue;

            var combined = string.Concat(textElements.Select(t => t.Text));
            if (!combined.Contains("{{")) continue;

            var replaced = PlaceholderRegex.Replace(combined, match =>
            {
                var key = match.Groups[1].Value;
                return data.TryGetValue(key, out var value) ? (value ?? string.Empty) : match.Value;
            });

            if (replaced == combined) continue;

            // Gán vào <w:t> đầu, clear rest (preserve run style của <w:t> đầu)
            textElements[0].Text = replaced;
            textElements[0].Space = new DocumentFormat.OpenXml.EnumValue<DocumentFormat.OpenXml.SpaceProcessingModeValues>(DocumentFormat.OpenXml.SpaceProcessingModeValues.Preserve);
            for (var i = 1; i < textElements.Count; i++)
                textElements[i].Text = string.Empty;
        }

        // Tables cũng có Paragraph lồng bên trong → đã được Descendants<Paragraph> bắt
    }
}
