package de.oaa.xxx.social;

import de.oaa.xxx.social.dto.PinnwandEintragDto;
import de.oaa.xxx.social.entity.PinnwandEintragEntity;
import de.oaa.xxx.social.repository.BlockRepository;
import de.oaa.xxx.social.repository.KommentarRepository;
import de.oaa.xxx.social.repository.PinnwandEintragRepository;
import de.oaa.xxx.social.repository.PinnwandLikeRepository;
import de.oaa.xxx.user.UserEntity;
import de.oaa.xxx.user.UserRepository;
import de.oaa.xxx.user.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/social/pinnwand")
public class PinnwandController {

    private static final Logger LOGGER = LoggerFactory.getLogger(PinnwandController.class);

    private final PinnwandEintragRepository eintragRepository;
    private final PinnwandLikeRepository likeRepository;
    private final KommentarRepository kommentarRepository;
    private final UserRepository userRepository;
    private final UserService userService;
    private final LikeService likeService;
    private final BlockRepository blockRepository;

    public PinnwandController(PinnwandEintragRepository eintragRepository,
                              PinnwandLikeRepository likeRepository,
                              KommentarRepository kommentarRepository,
                              UserRepository userRepository,
                              UserService userService,
                              LikeService likeService,
                              BlockRepository blockRepository) {
        this.eintragRepository = eintragRepository;
        this.likeRepository = likeRepository;
        this.kommentarRepository = kommentarRepository;
        this.userRepository = userRepository;
        this.userService = userService;
        this.likeService = likeService;
        this.blockRepository = blockRepository;
    }

    record CreateEintragRequest(UUID profilUserId, String text) {}

    @GetMapping
    public ResponseEntity<List<PinnwandEintragDto>> getEintraege(@RequestParam("userId") UUID userId, Principal principal) {
        UUID myId = userService.requireUser(principal).getUserId();

        List<PinnwandEintragDto> dtos = eintragRepository
                .findByProfilUserIdOrderByCreatedAtDesc(userId)
                .stream()
                .map(e -> toDto(e, myId))
                .toList();
        return ResponseEntity.ok(dtos);
    }

    @PostMapping
    public ResponseEntity<PinnwandEintragDto> createEintrag(@RequestBody CreateEintragRequest request, Principal principal) {
        UUID myId = userService.requireUser(principal).getUserId();

        if (request.text() == null || request.text().isBlank()) return ResponseEntity.badRequest().build();
        if (request.text().length() > 1000) return ResponseEntity.badRequest().build();

        // Blockiert? Profilinhaber kann keine Einträge von blockierten Personen erhalten
        if (blockRepository.findByBlockerIdAndBlockedId(request.profilUserId(), myId).isPresent()) {
            return ResponseEntity.status(403).build();
        }

        PinnwandEintragEntity entity = new PinnwandEintragEntity();
        entity.setEintragId(UUID.randomUUID());
        entity.setProfilUserId(request.profilUserId());
        entity.setAuthorId(myId);
        entity.setText(request.text().trim());
        entity.setCreatedAt(LocalDateTime.now());
        eintragRepository.save(entity);
        LOGGER.debug("User {} hat Pinnwand-Eintrag {} auf Profil {} erstellt", myId, entity.getEintragId(), request.profilUserId());

        return ResponseEntity.status(201).body(toDto(entity, myId));
    }

    @DeleteMapping("/{eintragId}")
    public ResponseEntity<Void> deleteEintrag(@PathVariable("eintragId") UUID eintragId, Principal principal) {
        UUID myId = userService.requireUser(principal).getUserId();

        var eintragOpt = eintragRepository.findById(eintragId);
        if (eintragOpt.isEmpty()) return ResponseEntity.notFound().build();
        var eintrag = eintragOpt.get();

        // Author or profile owner may delete
        if (!eintrag.getAuthorId().equals(myId) && !eintrag.getProfilUserId().equals(myId)) {
            return ResponseEntity.status(403).build();
        }

        likeRepository.deleteByEintragId(eintragId);
        // Delete comments on this entry (via KommentarRepository)
        kommentarRepository.findByTargetTypeAndTargetIdOrderByCreatedAtAsc("PINNWAND", eintragId)
                .forEach(k -> kommentarRepository.deleteById(k.getKommentarId()));
        eintragRepository.delete(eintrag);
        LOGGER.debug("User {} hat Pinnwand-Eintrag {} gelöscht", myId, eintragId);
        return ResponseEntity.noContent().build();
    }

    @PostMapping("/{eintragId}/like")
    public ResponseEntity<Void> toggleLike(@PathVariable("eintragId") UUID eintragId, Principal principal) {
        UUID myId = userService.requireUser(principal).getUserId();

        if (eintragRepository.findById(eintragId).isEmpty()) return ResponseEntity.notFound().build();

        likeService.togglePinnwandLike(eintragId, myId);
        return ResponseEntity.ok().build();
    }

    private PinnwandEintragDto toDto(PinnwandEintragEntity e, UUID myId) {
        UserEntity author = userRepository.findById(e.getAuthorId()).orElse(null);
        String authorName = author != null ? author.getName() : "Unbekannt";
        String authorPic = author != null ? author.getProfilePicture() : null;
        long likeCount = likeRepository.countByEintragId(e.getEintragId());
        boolean likedByMe = likeRepository.findByEintragIdAndUserId(e.getEintragId(), myId).isPresent();
        long kommentarCount = kommentarRepository.countByTargetTypeAndTargetId("PINNWAND", e.getEintragId());
        return new PinnwandEintragDto(e.getEintragId(), e.getProfilUserId(), e.getAuthorId(),
                authorName, authorPic, e.getText(), e.getCreatedAt(), likeCount, likedByMe, kommentarCount);
    }
}
