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

import com.cameleer.server.app.alerting.dto.AlertSilenceRequest;
import com.cameleer.server.app.alerting.dto.AlertSilenceResponse;
import com.cameleer.server.app.web.EnvPath;
import com.cameleer.server.core.admin.AuditCategory;
import com.cameleer.server.core.admin.AuditResult;
import com.cameleer.server.core.admin.AuditService;
import com.cameleer.server.core.alerting.AlertSilence;
import com.cameleer.server.core.alerting.AlertSilenceRepository;
import com.cameleer.server.core.runtime.Environment;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
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.Map;
import java.util.UUID;

/**
 * REST controller for alert silences (env-scoped).
 * VIEWER+ can list; OPERATOR+ can create/update/delete.
 */
@RestController
@RequestMapping("/api/v1/environments/{envSlug}/alerts/silences")
@Tag(name = "Alert Silences", description = "Alert silence management (env-scoped)")
@PreAuthorize("hasAnyRole('VIEWER','OPERATOR','ADMIN')")
public class AlertSilenceController {

    private final AlertSilenceRepository silenceRepo;
    private final AuditService auditService;

    public AlertSilenceController(AlertSilenceRepository silenceRepo,
                                  AuditService auditService) {
        this.silenceRepo = silenceRepo;
        this.auditService = auditService;
    }

    @GetMapping
    public List<AlertSilenceResponse> list(@EnvPath Environment env) {
        return silenceRepo.listByEnvironment(env.id())
                .stream().map(AlertSilenceResponse::from).toList();
    }

    @PostMapping
    @PreAuthorize("hasAnyRole('OPERATOR','ADMIN')")
    public ResponseEntity<AlertSilenceResponse> create(
            @EnvPath Environment env,
            @Valid @RequestBody AlertSilenceRequest req,
            HttpServletRequest httpRequest) {

        validateTimeRange(req);

        AlertSilence silence = new AlertSilence(
                UUID.randomUUID(), env.id(), req.matcher(), req.reason(),
                req.startsAt(), req.endsAt(),
                currentUserId(), Instant.now());

        AlertSilence saved = silenceRepo.save(silence);

        auditService.log("ALERT_SILENCE_CREATE", AuditCategory.ALERT_SILENCE_CHANGE,
                saved.id().toString(), Map.of(), AuditResult.SUCCESS, httpRequest);

        return ResponseEntity.status(HttpStatus.CREATED).body(AlertSilenceResponse.from(saved));
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAnyRole('OPERATOR','ADMIN')")
    public AlertSilenceResponse update(
            @EnvPath Environment env,
            @PathVariable UUID id,
            @Valid @RequestBody AlertSilenceRequest req,
            HttpServletRequest httpRequest) {

        AlertSilence existing = requireSilence(id, env.id());
        validateTimeRange(req);

        AlertSilence updated = new AlertSilence(
                existing.id(), env.id(), req.matcher(), req.reason(),
                req.startsAt(), req.endsAt(),
                existing.createdBy(), existing.createdAt());

        AlertSilence saved = silenceRepo.save(updated);

        auditService.log("ALERT_SILENCE_UPDATE", AuditCategory.ALERT_SILENCE_CHANGE,
                id.toString(), Map.of(), AuditResult.SUCCESS, httpRequest);

        return AlertSilenceResponse.from(saved);
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAnyRole('OPERATOR','ADMIN')")
    public ResponseEntity<Void> delete(
            @EnvPath Environment env,
            @PathVariable UUID id,
            HttpServletRequest httpRequest) {

        requireSilence(id, env.id());
        silenceRepo.delete(id);

        auditService.log("ALERT_SILENCE_DELETE", AuditCategory.ALERT_SILENCE_CHANGE,
                id.toString(), Map.of(), AuditResult.SUCCESS, httpRequest);

        return ResponseEntity.noContent().build();
    }

    // -------------------------------------------------------------------------
    // Helpers
    // -------------------------------------------------------------------------

    private void validateTimeRange(AlertSilenceRequest req) {
        if (!req.endsAt().isAfter(req.startsAt())) {
            throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY,
                    "endsAt must be after startsAt");
        }
    }

    private AlertSilence requireSilence(UUID id, UUID envId) {
        AlertSilence silence = silenceRepo.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "Alert silence not found: " + id));
        if (!silence.environmentId().equals(envId)) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND,
                    "Alert silence not found in this environment: " + id);
        }
        return silence;
    }

    private String currentUserId() {
        var auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth == null || auth.getName() == null) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "No authentication");
        }
        String name = auth.getName();
        return name.startsWith("user:") ? name.substring(5) : name;
    }
}
