using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace AyCode.Services.Nav;

/// <summary>
/// XML (de)szerializáció a NAV REST hívásokhoz. A NAV sima HTTP POST-ot vár, a body XML (UTF-8) — nincs SOAP.
/// A generált XSD-modellek <c>[XmlRoot]</c>/<c>[XmlElement]</c> attribútumai adják a namespace-t és a sorrendet.
/// </summary>
public static class NavXmlHelper
{
    /// <summary>
    /// A típust UTF-8 XML stringgé szerializálja. A <see cref="Utf8StringWriter"/> biztosítja, hogy az XML-deklaráció
    /// <c>encoding="utf-8"</c> legyen (a default <see cref="StringWriter"/> UTF-16-ot írna, amit a NAV elutasít).
    /// </summary>
    public static string Serialize<T>(T value)
    {
        var serializer = new XmlSerializer(typeof(T));
        using var stringWriter = new Utf8StringWriter();
        using var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings
        {
            Encoding = Encoding.UTF8,
            Indent = false,
            OmitXmlDeclaration = false,
        });
        serializer.Serialize(xmlWriter, value);
        return stringWriter.ToString();
    }

    /// <summary>A NAV válasz XML-t a megadott típusra deszerializálja.</summary>
    public static T Deserialize<T>(string xml)
    {
        var serializer = new XmlSerializer(typeof(T));
        using var reader = new StringReader(xml);
        return (T)serializer.Deserialize(reader)!;
    }

    /// <summary>
    /// <see cref="StringWriter"/>, ami UTF-8-at jelez — így az <see cref="XmlSerializer"/> az XML-deklarációba
    /// <c>encoding="utf-8"</c>-at ír. (A BCL alap <see cref="StringWriter"/>-e UTF-16-ot jelez.)
    /// </summary>
    private sealed class Utf8StringWriter : StringWriter
    {
        public override Encoding Encoding => Encoding.UTF8;
    }
}
