package de.assecutor.votianlt.pages.view;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.html.Span;
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasDynamicTitle;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageContentType;
import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType;
import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.service.MessageService;
import de.assecutor.votianlt.util.DateTimeFormatUtil;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Route(value = "user-messages", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed("USER")
@Slf4j
public class UserMessagesView extends Main implements HasUrlParameter<String>, HasDynamicTitle {

    private final AppUserService appUserService;
    private final MessageService messageService;

    private String participantKey;
    private VerticalLayout contentLayout;

    public UserMessagesView(AppUserService appUserService, MessageService messageService) {
        this.appUserService = appUserService;
        this.messageService = messageService;
        addClassName("message-hub-view");

        // Create main layout
        contentLayout = new VerticalLayout();
        contentLayout.setPadding(true);
        contentLayout.setSpacing(true);
        contentLayout.setWidthFull();
        contentLayout.addClassName("form-shell");

        add(contentLayout);
    }

    @Override
    public void setParameter(BeforeEvent event, String parameter) {
        this.participantKey = parameter;
        loadClientMessages();
    }

    private void loadClientMessages() {
        contentLayout.removeAll();

        // Get client info
        AppUser client = null;
        try {
            ObjectId objectId = new ObjectId(participantKey);
            client = appUserService.findById(objectId);
        } catch (Exception e) {
            log.debug("Could not resolve AppUser for participant key {}: {}", participantKey, e.getMessage());
        }

        String clientName = client != null ? client.getVorname() + " " + client.getNachname()
                : Optional.ofNullable(participantKey).orElse(getTranslation("usermessages.unknown.participant"));

        ViewToolbar headerLayout = createHeaderLayout(clientName);
        contentLayout.add(headerLayout);

        List<Message> conversation = messageService.getMessagesForAppUserAscending(participantKey);
        Map<MessageType, List<Message>> messagesByType = conversation.stream().collect(Collectors
                .groupingBy(message -> Optional.ofNullable(message.getMessageType()).orElse(MessageType.GENERAL)));

        addGeneralMessagesTo(contentLayout, messagesByType.get(MessageType.GENERAL));
        addJobMessagesTo(contentLayout, messagesByType.get(MessageType.JOB_RELATED));
    }

    private ViewToolbar createHeaderLayout(String clientName) {
        return new ViewToolbar(getTranslation("usermessages.title.with", clientName));
    }

    private void addGeneralMessagesTo(VerticalLayout target, List<Message> generalMessages) {
        H3 title = new H3(getTranslation("usermessages.general.title"));
        title.addClassName("message-section-title");
        target.add(title);

        List<Message> sortedMessages = new ArrayList<>();
        if (generalMessages != null) {
            sortedMessages.addAll(generalMessages);
        }

        sortedMessages
                .sort(Comparator.comparing(Message::getCreatedAt, Comparator.nullsLast(LocalDateTime::compareTo)));

        Message latest = sortedMessages.isEmpty() ? null : sortedMessages.get(sortedMessages.size() - 1);
        int unreadCount = (int) sortedMessages.stream()
                .filter(message -> message.getOrigin() == MessageOrigin.CLIENT && !message.isRead()).count();
        int messageCount = sortedMessages.size();
        LocalDateTime lastMessageTime = latest != null ? latest.getCreatedAt() : null;
        String preview = resolvePreview(latest);

        target.add(createMessageCard(getTranslation("usermessages.general.conversation"), preview, lastMessageTime,
                messageCount, unreadCount, "general"));
    }

    private void addJobMessagesTo(VerticalLayout target, List<Message> jobMessages) {
        H3 title = new H3(getTranslation("usermessages.job.title"));
        title.addClassName("message-section-title");
        target.add(title);

        if (jobMessages == null || jobMessages.isEmpty()) {
            target.add(new Span(getTranslation("usermessages.no.job.messages")));
            return;
        }

        Map<String, List<Message>> messagesByJob = jobMessages.stream()
                .collect(Collectors.groupingBy(this::resolveJobKey, LinkedHashMap::new, Collectors.toList()));

        messagesByJob.forEach((jobKey, messages) -> {
            messages.sort(Comparator.comparing(Message::getCreatedAt, Comparator.nullsLast(LocalDateTime::compareTo)));
            Message latest = messages.get(messages.size() - 1);
            int unreadCount = (int) messages.stream()
                    .filter(message -> message.getOrigin() == MessageOrigin.CLIENT && !message.isRead()).count();

            String conversationTitle = getTranslation("usermessages.job.conversation", jobKey);
            target.add(createMessageCard(conversationTitle, resolvePreview(latest), latest.getCreatedAt(),
                    messages.size(), unreadCount, "job-" + sanitizeConversationId(jobKey)));
        });
    }

    private String resolvePreview(Message message) {
        if (message == null) {
            return "";
        }

        if (message.getContentType() == MessageContentType.IMAGE) {
            return getTranslation("messages.preview.image");
        }

        return Optional.ofNullable(message.getContent()).map(String::trim).orElse("");
    }

    private Div createMessageCard(String conversationTitle, String lastMessagePreview, LocalDateTime lastMessageTime,
            int messageCount, int unreadCount, String conversationId) {
        Div card = new Div();
        card.setWidthFull();
        card.getStyle().set("cursor", "pointer");
        card.addClassName("message-card");

        // Title row with unread indicator
        HorizontalLayout titleRow = new HorizontalLayout();
        titleRow.setWidthFull();
        titleRow.setAlignItems(com.vaadin.flow.component.orderedlayout.FlexComponent.Alignment.CENTER);
        titleRow.setSpacing(true);

        Span titleSpan = new Span(conversationTitle);
        titleSpan.addClassName("message-section-title");

        if (unreadCount > 0) {
            Span unreadBadge = new Span(String.valueOf(unreadCount));
            unreadBadge.addClassName("message-badge");
            titleRow.add(titleSpan, unreadBadge);
        } else {
            titleRow.add(titleSpan);
        }

        titleRow.expand(titleSpan);

        // Preview text
        Span preview = new Span(Optional.ofNullable(lastMessagePreview).filter(s -> !s.isBlank())
                .orElse(getTranslation("usermessages.preview.empty")));
        preview.addClassName("message-preview");

        // Metadata row
        HorizontalLayout metaRow = new HorizontalLayout();
        metaRow.setWidthFull();
        metaRow.addClassName("message-meta");

        Span timeSpan = new Span(lastMessageTime != null ? DateTimeFormatUtil.formatDateTime(lastMessageTime) : "-");

        Span countSpan = new Span(getTranslation("usermessages.message.count", messageCount));

        metaRow.add(timeSpan, countSpan);
        metaRow.expand(timeSpan);

        // Add all elements to card
        VerticalLayout cardContent = new VerticalLayout(titleRow, preview, metaRow);
        cardContent.setWidthFull();
        cardContent.setPadding(true);
        cardContent.setSpacing(false);
        card.add(cardContent);

        // Click listener to navigate to message details
        card.addClickListener(
                e -> UI.getCurrent().navigate("message-details/" + participantKey + "/" + conversationId));

        return card;
    }

    private String resolveJobKey(Message message) {
        if (message == null) {
            return getTranslation("usermessages.unknown");
        }
        String jobNumber = Optional.ofNullable(message.getJobNumber()).filter(s -> !s.isBlank()).orElse(null);
        if (jobNumber != null) {
            return jobNumber;
        }
        String jobId = message.getJobIdAsString();
        if (jobId != null && !jobId.isBlank()) {
            return jobId;
        }
        return getTranslation("usermessages.unknown");
    }

    private String sanitizeConversationId(String value) {
        if (value == null || value.isBlank()) {
            return "unknown";
        }
        return value.replaceAll("[^a-zA-Z0-9_-]", "_");
    }

    @Override
    public String getPageTitle() {
        return getTranslation("page.title.user.messages");
    }
}
