using WebPush;

namespace Service;

public interface INotificationService
{
    Task<string> GetVapidPublicKeyAsync();
    Task SubscribeAsync(Entity.PushSubscription subscription);
    Task SendNotificationAsync(string message, string? url = null);
}

public class NotificationService(
    IPushSubscriptionRepository subscriptionRepo,
    IConfiguration configuration,
    ILogger<NotificationService> logger) : INotificationService
{
    private NotificationSettings GetSettings()
    {
        var settings = configuration.GetSection("NotificationSettings").Get<NotificationSettings>();
        if (settings == null)
        {
            // Fallback or throw. For now, let's return empty to avoid crashing if not configured, 
            // but logging error is better.
            logger.LogWarning("NotificationSettings not configured");
            return new NotificationSettings();
        }
        return settings;
    }

    public Task<string> GetVapidPublicKeyAsync()
    {
        return Task.FromResult(GetSettings().PublicKey);
    }

    public async Task SubscribeAsync(Entity.PushSubscription subscription)
    {
        var existing = await subscriptionRepo.GetByEndpointAsync(subscription.Endpoint);
        if (existing != null)
        {
            existing.P256DH = subscription.P256DH;
            existing.Auth = subscription.Auth;
            existing.UpdateTime = DateTime.Now;
            await subscriptionRepo.UpdateAsync(existing);
        }
        else
        {
            await subscriptionRepo.AddAsync(subscription);
        }
    }

    public async Task SendNotificationAsync(string message, string? url = null)
    {
        var settings = GetSettings();
        if (string.IsNullOrEmpty(settings.PublicKey) || string.IsNullOrEmpty(settings.PrivateKey))
        {
            logger.LogWarning("VAPID keys not configured, skipping notification");
            return;
        }

        var vapidDetails = new VapidDetails(settings.Subject, settings.PublicKey, settings.PrivateKey);
        var webPushClient = new WebPushClient();

        var subscriptions = await subscriptionRepo.GetAllAsync();
        var payload = System.Text.Json.JsonSerializer.Serialize(new
        {
            title = "System Notification",
            body = message,
            url = url ?? "/",
            icon = "/pwa-192x192.png"
        });

        foreach (var sub in subscriptions)
        {
            try
            {
                var pushSubscription = new WebPush.PushSubscription(sub.Endpoint, sub.P256DH, sub.Auth);
                await webPushClient.SendNotificationAsync(pushSubscription, payload, vapidDetails);
            }
            catch (WebPushException ex)
            {
                if (ex.StatusCode == System.Net.HttpStatusCode.Gone || ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    await subscriptionRepo.DeleteAsync(sub.Id);
                }
                logger.LogError(ex, "Error sending push notification to {Endpoint}", sub.Endpoint);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Error sending push notification to {Endpoint}", sub.Endpoint);
            }
        }
    }
}
