using System.Text.Json;
using Microsoft.ApplicationInsights;
using PlanTempus.Core.CommandQueries;
using PlanTempus.Core.Email;
using PlanTempus.Core.Outbox;

namespace PlanTempus.Components.Outbox;

public class ProcessOutboxHandler(
	IOutboxService outboxService,
	IEmailService emailService,
	TelemetryClient telemetryClient) : ICommandHandler<ProcessOutboxCommand>
{
	public async Task<CommandResponse> Handle(ProcessOutboxCommand command)
	{
		Console.WriteLine($"ProcessOutboxHandler started");
		telemetryClient.TrackTrace($"ProcessOutboxHandler started");

		var messages = await outboxService.GetPendingAsync(command.BatchSize);

		Console.WriteLine($"ProcessOutboxHandler found {messages.Count} pending messages");
		telemetryClient.TrackTrace($"ProcessOutboxHandler found {messages.Count} pending messages");

		foreach (var message in messages)
		{
			try
			{
				Console.WriteLine($"Processing message {message.Id} of type {message.Type}");
				telemetryClient.TrackTrace($"Processing message {message.Id} of type {message.Type}");
				await ProcessMessageAsync(message);
				await outboxService.MarkAsSentAsync(message.Id);
				Console.WriteLine($"Message {message.Id} marked as sent");
				telemetryClient.TrackTrace($"Message {message.Id} marked as sent");
			}
			catch (Exception ex)
			{
				Console.WriteLine($"Message {message.Id} failed: {ex.Message}");
				telemetryClient.TrackTrace($"Message {message.Id} failed: {ex.Message}");
				await outboxService.MarkAsFailedAsync(message.Id, ex.Message);
			}
		}

		return new CommandResponse(command.CorrelationId, nameof(ProcessOutboxCommand), command.TransactionId);
	}

	private async Task ProcessMessageAsync(OutboxMessage message)
	{
		switch (message.Type)
		{
			case OutboxMessageTypes.VerificationEmail:
				await ProcessVerificationEmailAsync(message);
				break;

			default:
				throw new InvalidOperationException($"Unknown outbox message type: {message.Type}");
		}
	}

	private async Task ProcessVerificationEmailAsync(OutboxMessage message)
	{
		var payload = ((JsonElement)message.Payload).Deserialize<VerificationEmailPayload>()
			?? throw new InvalidOperationException("Invalid verification email payload");

		var verifyUrl = $"https://plantempus.dk/confirm-email?token={payload.Token}";

		var result = await emailService.SendVerificationEmailAsync(
			payload.Email,
			payload.UserName,
			verifyUrl);

		if (!result.Success)
		{
			throw new InvalidOperationException($"Failed to send email: {result.ErrorMessage}");
		}
	}
}
