package de.cannamanage.service.push;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Map;

/**
 * Web Push sender using VAPID keys.
 * Sends push notifications to browser service workers via the Web Push protocol.
 * <p>
 * For MVP: uses raw HTTP push with simple JSON payload.
 * If credentials are not configured, logs a warning and skips.
 */
@Slf4j
@Service
public class WebPushSender {

    @Value("${push.vapid.public-key:}")
    private String vapidPublicKey;

    @Value("${push.vapid.private-key:}")
    private String vapidPrivateKey;

    @Value("${push.vapid.subject:mailto:admin@cannamanage.de}")
    private String vapidSubject;

    private final HttpClient httpClient = HttpClient.newHttpClient();

    /**
     * Send a push notification to a Web Push subscription.
     *
     * @param subscriptionJson the full subscription JSON (endpoint, keys.p256dh, keys.auth)
     * @param payload          the notification payload
     */
    public void send(String subscriptionJson, PushPayload payload) {
        if (vapidPublicKey.isBlank() || vapidPrivateKey.isBlank()) {
            log.debug("VAPID keys not configured — skipping Web Push");
            return;
        }

        try {
            // Extract endpoint from subscription JSON (simple parsing without Jackson)
            var endpoint = extractJsonString(subscriptionJson, "endpoint");

            if (endpoint == null || endpoint.isBlank()) {
                log.warn("Invalid Web Push subscription — missing endpoint");
                return;
            }

            // Build payload JSON manually
            var payloadJson = buildPayloadJson(payload);

            // Simplified push: send payload to push endpoint
            // Full VAPID auth + encryption (RFC 8291) should be added when web-push-java lib is integrated
            var request = HttpRequest.newBuilder()
                    .uri(URI.create(endpoint))
                    .header("Content-Type", "application/json")
                    .header("TTL", "86400")
                    .POST(HttpRequest.BodyPublishers.ofString(payloadJson))
                    .build();

            var response = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
            response.thenAccept(r -> {
                if (r.statusCode() == 201) {
                    log.debug("Web Push sent successfully to {}...", endpoint.substring(0, Math.min(50, endpoint.length())));
                } else if (r.statusCode() == 410) {
                    log.info("Web Push subscription expired (410 Gone): {}...", endpoint.substring(0, Math.min(50, endpoint.length())));
                } else {
                    log.warn("Web Push failed with status {}: {}", r.statusCode(), r.body());
                }
            });

        } catch (Exception e) {
            log.error("Failed to send Web Push: {}", e.getMessage());
        }
    }

    /**
     * Check if Web Push is configured and ready to send.
     */
    public boolean isConfigured() {
        return !vapidPublicKey.isBlank() && !vapidPrivateKey.isBlank();
    }

    public String getPublicKey() {
        return vapidPublicKey;
    }

    private String buildPayloadJson(PushPayload payload) {
        return "{" +
                "\"title\":\"" + escapeJson(payload.getTitle()) + "\"," +
                "\"body\":\"" + escapeJson(payload.getBody()) + "\"," +
                "\"icon\":\"" + escapeJson(payload.getIcon() != null ? payload.getIcon() : "/icons/icon-192.png") + "\"," +
                "\"badge\":\"/icons/icon-192.png\"," +
                "\"type\":\"" + escapeJson(payload.getType() != null ? payload.getType() : "default") + "\"," +
                "\"url\":\"" + escapeJson(payload.getUrl() != null ? payload.getUrl() : "/portal/notifications") + "\"" +
                "}";
    }

    private String extractJsonString(String json, String key) {
        var searchKey = "\"" + key + "\"";
        int keyIdx = json.indexOf(searchKey);
        if (keyIdx < 0) return null;

        int colonIdx = json.indexOf(':', keyIdx + searchKey.length());
        if (colonIdx < 0) return null;

        int startQuote = json.indexOf('"', colonIdx + 1);
        if (startQuote < 0) return null;

        int endQuote = json.indexOf('"', startQuote + 1);
        if (endQuote < 0) return null;

        return json.substring(startQuote + 1, endQuote);
    }

    private String escapeJson(String value) {
        if (value == null) return "";
        return value
                .replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }
}
