@page "/Email/Unsubscribe"
@using Microsoft.AspNetCore.Identity.UI.Services
@using Microsoft.EntityFrameworkCore
@using Wave.Data
@using Wave.Services
@using Wave.Utilities

@inject ILogger<EmailEdit> Logger
@inject IStringLocalizer<EmailEdit> Localizer
@inject IDbContextFactory<ApplicationDbContext> ContextFactory
@inject IEmailSender EmailSender
@inject EmailTemplateService TemplateService
@inject IMessageDisplay Messages

<HeadContent>
	<meta name="robots" content="noindex,nofollow">
</HeadContent>

<PageTitle>@(Localizer["Title"] + TitlePostfix)</PageTitle>

<BoardComponent CenterContent="true">
	<BoardCardComponent Heading="@Localizer["Title"]">
		<form method="post" @formname="Unsubscribe" @onsubmit="Unsubscribe_Submit">
			<AntiforgeryToken />
			<input type="hidden" name="user" value="@Id" />
			<input type="hidden" name="token" value="@Token" />
			<input type="hidden" name="newsletter" value="@Newsletter" />
			
			<button type="submit" class="btn btn-error w-full">@Localizer["Submit_Unsubscribe"]</button>
		</form>

	</BoardCardComponent>
</BoardComponent>

@code {
	[CascadingParameter(Name = "TitlePostfix")]
	private string TitlePostfix { get; set; } = default!;
	
	[Parameter, SupplyParameterFromQuery(Name = "user")]
	public string? Id { get; set; }
	[Parameter, SupplyParameterFromQuery(Name = "token")]
	public string? Token { get; set; }
	[Parameter, SupplyParameterFromQuery(Name = "newsletter")]
	public string? Newsletter { get; set; }

	[CascadingParameter]
	public HttpContext? HttpContext { get; set; } 

	protected override async Task OnInitializedAsync() {
		if (Id is null || Token is null || Newsletter is null) {
			if (HttpContext?.Request.Method.ToUpper() is "POST") 
				Messages.ShowError(Localizer["Load_Failure_Message"]);
			return;
		}

		try {
			if (await GetSubscriber() is null) {
				Messages.ShowError(Localizer["Load_Failure_Message"]);
			}
		} catch (Exception) {
			Messages.ShowError(Localizer["Load_Failure_Message"]);
		}
	}

	private async Task Unsubscribe_Submit() {
		try {
			await using var context = await ContextFactory.CreateDbContextAsync();
			var subscriber = await GetSubscriber(context);
			if (subscriber is null) {
				Messages.ShowError(Localizer["Unsubscribe_Failure_Message"]);
				return;
			}

			subscriber.Unsubscribed = true;
			subscriber.UnsubscribeReason = "User used unsubscribe Link";
			await context.SaveChangesAsync();
			Messages.ShowSuccess(Localizer["Unsubscribe_Success"]);

			await EmailSender.SendEmailAsync(subscriber.Email, Localizer["ConfirmEmailSubject"], Localizer["Unsubscribe_ConfirmEmailBody"]);
			await TemplateService.ValidateTokensAsync(Id!, Token!, "unsubscribe-" + Newsletter); // delete token
		} catch (EmailNotSendException ex) {
			Logger.LogWarning(ex, "Failed to send unsubscribe confirm email. The user has been unsubscribed anyway.");
		} catch (Exception) {
			Messages.ShowError(Localizer["Unsubscribe_Failure_Message"]);
		}
	}

	private async Task<EmailSubscriber?> GetSubscriber(ApplicationDbContext? context = null) {
		if (Id is null || Token is null || Newsletter is null) {
			return null;
		}

		var id = await TemplateService.ValidateTokensAsync(Id, Token, "unsubscribe-" + Newsletter, false);
		if (id is null) {
			return null;
		}

		if (context is null) {
			await using var context1 = await ContextFactory.CreateDbContextAsync();
			return context1.Set<EmailSubscriber>().FirstOrDefault(s => s.Id == id);
		}

		return context.Set<EmailSubscriber>().FirstOrDefault(s => s.Id == id);
	}
}
