📄 MatDenDagen/Components/Pages/Submission.razor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MatDenDagen.Infrastructure.Storage.BlobStorage;
using MatDenDagen.Infrastructure.Storage.Database;
using MatDenDagen.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;

namespace MatDenDagen.Components.Pages;

public partial class Submission(
    TimeProvider timeProvider,
    BlobStorageService blobService,
    QuestionnaireContext questionnaireContext
)
{
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    private bool success = false;

    private List<Question> questions = [];

    private string? errorMessage = null;

    protected override async Task OnInitializedAsync()
    {
        questions = await questionnaireContext.Questions.ToListAsync(
            HttpContext?.RequestAborted ?? CancellationToken.None
        );

        if (HttpContext?.Request.Method is not "POST")
            return;

        var form = HttpContext.Request.Form;

        var phoneNumber = form["phoneNumber"].FirstOrDefault();
        if (phoneNumber is null)
        {
            errorMessage = "Telefonnummer är obligatoriskt.";
            return;
        }
        List<string> phoneNumberVariants = [phoneNumber, nonDigits.Replace(phoneNumber, "")];
        if (phoneNumber.StartsWith("+46"))
        {
            phoneNumberVariants.Add(phoneNumber[3..]);
            phoneNumberVariants.Add(nonDigits.Replace(phoneNumber[3..], ""));
        }

        var participant = await questionnaireContext.Participants.SingleOrDefaultAsync(
            p => phoneNumberVariants.Contains(p.PhoneNumber),
            HttpContext.RequestAborted
        );

        if (participant is null)
        {
            errorMessage =
                "Okänt telefonnummer. Var god kontakta administratören för att registrera ditt telefonnummer.";
            return;
        }

        var uploads = new List<Upload>();
        foreach (var file in form.Files)
        {
            await using var stream = file.OpenReadStream();
            var result = await blobService.SaveBlob(stream, HttpContext.RequestAborted);
            uploads.Add(new Upload { Id = result.Id, Name = file.FileName });
        }

        questionnaireContext.Submissions.Add(
            new()
            {
                Id = Guid.CreateVersion7(timeProvider.GetUtcNow()),
                Answers =
                [
                    .. questions.Select(q => new Answer
                    {
                        Id = Guid.CreateVersion7(timeProvider.GetUtcNow()),
                        QuestionId = q.Id,
                        Text = form[$"answer[{q.Id}]"].ToString(),
                    }),
                ],
                Uploads = uploads,
                Participant = participant.Id,
            }
        );
        await questionnaireContext.SaveChangesAsync(HttpContext.RequestAborted);

        success = true;
    }

    [GeneratedRegex(@"[^\d]+")]
    private partial Regex nonDigits { get; }
}