package com.cameleer.server.app.alerting.controller;

import com.cameleer.server.app.alerting.dto.AlertNotificationDto;
import com.cameleer.server.app.web.EnvPath;
import com.cameleer.server.core.alerting.AlertNotification;
import com.cameleer.server.core.alerting.AlertNotificationRepository;
import com.cameleer.server.core.alerting.NotificationStatus;
import com.cameleer.server.core.runtime.Environment;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import java.time.Instant;
import java.util.List;
import java.util.UUID;

/**
 * REST controller for alert notifications.
 * <p>
 * Env-scoped: GET /api/v1/environments/{envSlug}/alerts/{id}/notifications — lists outbound
 * notifications for a given alert instance.
 * <p>
 * Flat: POST /api/v1/alerts/notifications/{id}/retry — globally unique notification IDs;
 * flat path matches the /executions/{id} precedent. OPERATOR+ only.
 */
@RestController
@Tag(name = "Alert Notifications", description = "Outbound webhook notification management")
public class AlertNotificationController {

    private final AlertNotificationRepository notificationRepo;

    public AlertNotificationController(AlertNotificationRepository notificationRepo) {
        this.notificationRepo = notificationRepo;
    }

    /**
     * Lists notifications for a specific alert instance (env-scoped).
     * VIEWER+.
     */
    @GetMapping("/api/v1/environments/{envSlug}/alerts/{alertId}/notifications")
    @PreAuthorize("hasAnyRole('VIEWER','OPERATOR','ADMIN')")
    public List<AlertNotificationDto> listForInstance(
            @EnvPath Environment env,
            @PathVariable UUID alertId) {
        return notificationRepo.listForInstance(alertId)
                .stream().map(AlertNotificationDto::from).toList();
    }

    /**
     * Retries a failed notification — resets attempts and schedules it for immediate retry.
     * Notification IDs are globally unique (flat path, matches /executions/{id} precedent).
     * OPERATOR+ only.
     */
    @PostMapping("/api/v1/alerts/notifications/{id}/retry")
    @PreAuthorize("hasAnyRole('OPERATOR','ADMIN')")
    public AlertNotificationDto retry(@PathVariable UUID id) {
        AlertNotification notification = notificationRepo.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "Notification not found: " + id));

        if (notification.status() == NotificationStatus.PENDING) {
            return AlertNotificationDto.from(notification);
        }

        // Reset for retry: status -> PENDING, attempts -> 0, next_attempt_at -> now
        notificationRepo.resetForRetry(id, Instant.now());

        return AlertNotificationDto.from(notificationRepo.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)));
    }
}
