using System.Globalization;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Gotenberg.Sharp.API.Client;
using Gotenberg.Sharp.API.Client.Domain.Builders;

namespace Otchinslator.Services;

public interface IStatementGenerator
{
    public Task<MemoryStream> GenerateStatementAsync(UserData userData, string TemplateName = "ictis.docx");
    public Task<Stream> ConvertToPDFAsync(MemoryStream stream);
}

public class StatementGenerator(GotenbergSharpClient gotenbergSharpClient) : IStatementGenerator
{
    private static readonly List<string> Bookmarks = new() { "phone", "reason", "email", "kurs", "date", "fio", "paid_or_free", "ochno_or_zaochno", "speciality" };
    private const string SpecialitetText = "специалитета по специальности";
    private const string BakalavriatText = "бакалавриата по направлению подготовки";
    private const string MagistaturaText = "магистратуры по направлению подготовки";
    private const string FreeEducationText = "за счет ассигнований федерального бюджета";
    private const string PaidEducationText = "на договорной (платной) основе";
    
    // TODO: Выбор темплейтов не реализован
    public async Task<MemoryStream> GenerateStatementAsync(UserData userData, string TemplateName = "ictis.docx")
    {
        byte[] textByteArray = File.ReadAllBytes("Templates/" + TemplateName);
        MemoryStream stream = new MemoryStream();
        stream.Write(textByteArray, 0, textByteArray.Length);
        using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
        {
            var bookMarks = Utils.FindBookmarks(doc.MainDocumentPart.Document);

            foreach (var end in bookMarks)
            {
                if (!Bookmarks.Contains(end.Key)) continue;
                    
                var textElement = new Text();
                switch (end.Key)
                {
                    case "phone":
                        textElement.Text = userData.phone;
                        break;
                    case "email":
                        textElement.Text = userData.email;
                        break;
                    case "kurs":
                        textElement.Text = userData.kurs.ToString();
                        break;
                    case "fio":
                        textElement.Text = userData.fio;
                        break;
                    case "paid_or_free":
                        textElement.Text = userData.isFreeEducation ? FreeEducationText : PaidEducationText;
                        break;
                    case "ochno_or_zaochno":
                        textElement.Text = userData.isOchno ? "очной" : "очно-заочной";
                        break;
                    case "date":
                        textElement.Text = DateTime.UtcNow.AddHours(3).ToString(CultureInfo.InvariantCulture.DateTimeFormat.ShortDatePattern);
                        break;
                    case "reason":
                        textElement.Text = userData.reason;
                        break;
                    case "speciality":
                        textElement.Text = userData.speciality switch
                        {
                            SpecialityType.Bakalavriat => BakalavriatText,
                            SpecialityType.Magistatura => MagistaturaText,
                            SpecialityType.Specialitet => SpecialitetText,
                            _ => throw new ArgumentOutOfRangeException()
                        } + " " + userData.direction;
                        break;
                }

                // Далее данный текст добавляем в закладку
                var runElement = new Run(textElement);
                end.Value.InsertAfterSelf(runElement);
            }
        }
        return stream;
    }

    public async Task<Stream> ConvertToPDFAsync(MemoryStream stream)
    {
        var builder =
            new MergeOfficeBuilder().WithAssets(a =>
                a.AddItem("test1.docx", stream.ToArray()));
        var request = await builder.BuildAsync();
        return await gotenbergSharpClient.MergeOfficeDocsAsync(request);
    }
}