package com.alttd.altitudeweb.controllers.event;

import com.alttd.altitudeweb.controllers.chat.ChatMessageMapper;
import com.alttd.altitudeweb.model.PermissionClaimDto;
import com.alttd.altitudeweb.services.chat.ChatService;
import com.alttd.altitudeweb.services.chat.event_publisher.EventPublisher;
import com.alttd.altitudeweb.services.chat.event_publisher.EventUser;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Slf4j
@RestController
@RequestMapping("/api/chat/read")
public class EventController {

    private final static Duration MESSAGE_HISTORY_DURATION = Duration.ofHours(1);
    private final ChatService chatService;
    private final EventPublisher eventPublisher;

    @GetMapping(path = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe(@AuthenticationPrincipal Jwt jwt,
                                HttpServletResponse response) {
        if (jwt == null) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
        }

        List<String> authorities = jwt.getClaimAsStringList("authorities");
        if (authorities == null || !authorities.contains(PermissionClaimDto.HEAD_MOD.getValue())) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN);
        }

        response.setHeader("X-Accel-Buffering", "no"); // disables nginx buffering if present
        response.setHeader("Cache-Control", "no-cache");

        UUID subject;
        try {
            subject = UUID.fromString(jwt.getSubject());
        } catch (IllegalArgumentException e) {
            log.error("Invalid UUID in JWT subject: {}", jwt.getSubject());
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
        }

        String json = chatService.getMessagesSince(Instant.now().minus(MESSAGE_HISTORY_DURATION))
                .stream()
                .map(ChatMessageMapper::toJson)
                .collect(Collectors.joining(",", "[", "]"));

        return eventPublisher.subscribe(new EventUser(subject, authorities), json);
    }
}
