package de.cannamanage.api.controller;

import de.cannamanage.domain.entity.InfoBoardPost;
import de.cannamanage.domain.enums.InfoBoardCategory;
import de.cannamanage.service.InfoBoardService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.UUID;

/**
 * Info Board (Schwarzes Brett) endpoints for admin and portal.
 */
@RestController
@RequiredArgsConstructor
public class InfoBoardController {

    private final InfoBoardService infoBoardService;

    // ============================================================
    // ADMIN ENDPOINTS (require MANAGE_INFO_BOARD permission)
    // ============================================================

    /**
     * Create a new info board post.
     */
    @PostMapping("/api/v1/info-board")
    public ResponseEntity<?> createPost(
            @Valid @RequestBody CreatePostRequest request,
            @AuthenticationPrincipal UserDetails user) {

        UUID authorId = UUID.fromString(user.getUsername());
        InfoBoardPost post = infoBoardService.createPost(
                request.clubId(), request.title(), request.content(),
                request.category(), request.pinned() != null && request.pinned(), authorId);

        return ResponseEntity.ok(toResponse(post));
    }

    /**
     * List posts (admin view with optional filters).
     */
    @GetMapping("/api/v1/info-board")
    public ResponseEntity<?> listPosts(
            @RequestParam UUID clubId,
            @RequestParam(required = false) InfoBoardCategory category,
            @RequestParam(defaultValue = "false") boolean includeArchived,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {

        Page<InfoBoardPost> posts = infoBoardService.getPosts(clubId, category, includeArchived, page, size);
        var items = posts.getContent().stream().map(this::toResponse).toList();

        return ResponseEntity.ok(Map.of(
                "posts", items,
                "totalElements", posts.getTotalElements(),
                "totalPages", posts.getTotalPages(),
                "page", posts.getNumber()
        ));
    }

    /**
     * Get a single post.
     */
    @GetMapping("/api/v1/info-board/{id}")
    public ResponseEntity<?> getPost(@PathVariable UUID id) {
        InfoBoardPost post = infoBoardService.getPost(id);
        return ResponseEntity.ok(toResponse(post));
    }

    /**
     * Update a post.
     */
    @PutMapping("/api/v1/info-board/{id}")
    public ResponseEntity<?> updatePost(
            @PathVariable UUID id,
            @Valid @RequestBody UpdatePostRequest request) {

        InfoBoardPost post = infoBoardService.updatePost(
                id, request.title(), request.content(), request.category(), request.pinned());
        return ResponseEntity.ok(toResponse(post));
    }

    /**
     * Delete a post.
     */
    @DeleteMapping("/api/v1/info-board/{id}")
    public ResponseEntity<?> deletePost(@PathVariable UUID id) {
        infoBoardService.deletePost(id);
        return ResponseEntity.ok(Map.of("deleted", true));
    }

    /**
     * Archive a post.
     */
    @PostMapping("/api/v1/info-board/{id}/archive")
    public ResponseEntity<?> archivePost(@PathVariable UUID id) {
        InfoBoardPost post = infoBoardService.archivePost(id);
        return ResponseEntity.ok(toResponse(post));
    }

    /**
     * Unarchive a post.
     */
    @PostMapping("/api/v1/info-board/{id}/unarchive")
    public ResponseEntity<?> unarchivePost(@PathVariable UUID id) {
        InfoBoardPost post = infoBoardService.unarchivePost(id);
        return ResponseEntity.ok(toResponse(post));
    }

    /**
     * Toggle pin status.
     */
    @PostMapping("/api/v1/info-board/{id}/pin")
    public ResponseEntity<?> togglePin(@PathVariable UUID id) {
        InfoBoardPost post = infoBoardService.togglePin(id);
        return ResponseEntity.ok(toResponse(post));
    }

    // ============================================================
    // PORTAL ENDPOINTS (member access)
    // ============================================================

    /**
     * Get posts for the member's club (non-archived, pinned first).
     */
    @GetMapping("/api/v1/portal/info-board")
    public ResponseEntity<?> getPortalPosts(
            @RequestParam UUID clubId,
            @RequestParam(required = false) InfoBoardCategory category,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {

        Page<InfoBoardPost> posts = infoBoardService.getPosts(clubId, category, false, page, size);
        var items = posts.getContent().stream().map(this::toResponse).toList();

        return ResponseEntity.ok(Map.of(
                "posts", items,
                "totalElements", posts.getTotalElements(),
                "totalPages", posts.getTotalPages(),
                "page", posts.getNumber()
        ));
    }

    /**
     * Mark a post as read.
     */
    @PostMapping("/api/v1/portal/info-board/{id}/read")
    public ResponseEntity<?> markAsRead(
            @PathVariable UUID id,
            @RequestParam UUID memberId) {
        infoBoardService.markAsRead(id, memberId);
        return ResponseEntity.ok(Map.of("read", true));
    }

    /**
     * Get unread post count for badge display.
     */
    @GetMapping("/api/v1/portal/info-board/unread-count")
    public ResponseEntity<?> getUnreadCount(
            @RequestParam UUID clubId,
            @RequestParam UUID memberId) {
        long count = infoBoardService.getUnreadCount(clubId, memberId);
        return ResponseEntity.ok(Map.of("unreadCount", count));
    }

    // ============================================================
    // DTOs
    // ============================================================

    public record CreatePostRequest(
            @NotNull UUID clubId,
            @NotBlank @Size(max = 200) String title,
            @NotBlank String content,
            @NotNull InfoBoardCategory category,
            Boolean pinned
    ) {}

    public record UpdatePostRequest(
            @Size(max = 200) String title,
            String content,
            InfoBoardCategory category,
            Boolean pinned
    ) {}

    // ============================================================
    // Response mapping
    // ============================================================

    private Map<String, Object> toResponse(InfoBoardPost post) {
        return Map.of(
                "id", post.getId(),
                "clubId", post.getClubId(),
                "title", post.getTitle(),
                "content", post.getContent(),
                "category", post.getCategory().name(),
                "pinned", post.isPinned(),
                "archived", post.isArchived(),
                "authorId", post.getAuthorId(),
                "createdAt", post.getCreatedAt().toString(),
                "updatedAt", post.getUpdatedAt() != null ? post.getUpdatedAt().toString() : ""
        );
    }
}
