package de.assecutor.votianlt.pages.base.ui.view;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.DetachEvent;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.avatar.Avatar;
import com.vaadin.flow.component.avatar.AvatarVariant;
import com.vaadin.flow.component.details.Details;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.Scroller;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.sidenav.SideNav;
import com.vaadin.flow.component.sidenav.SideNavItem;
import com.vaadin.flow.router.Layout;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.server.menu.MenuConfiguration;
import com.vaadin.flow.server.menu.MenuEntry;
import com.vaadin.flow.shared.Registration;
import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.model.UserInvoiceData;
import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.pages.service.UserInvoiceDataService;
import de.assecutor.votianlt.pages.view.EditProfileView;
import de.assecutor.votianlt.security.SecurityService;
import de.assecutor.votianlt.service.MessageBadgeUpdateService;
import de.assecutor.votianlt.service.MessageService;
import lombok.extern.slf4j.Slf4j;

import static com.vaadin.flow.theme.lumo.LumoUtility.*;

import java.util.List;

@AnonymousAllowed
@Slf4j
@Layout("main")
public final class MainLayout extends AppLayout {

    private final SecurityService securityService;
    private final UserInvoiceDataService userInvoiceDataService;
    private final MessageService messageService;
    private final MessageBadgeUpdateService messageBadgeUpdateService;
    private final AppUserService appUserService;
    private Div headerRef;
    private Scroller navRef;
    private Component userMenuRef;
    private Span messagesBadge; // Reference to the messages badge for dynamic updates
    private SideNavItem messagesNavItem; // Reference to the messages nav item
    private Registration badgeUpdateRegistration; // Track badge update listener registration

    public MainLayout(SecurityService securityService, UserInvoiceDataService userInvoiceDataService,
            MessageService messageService, MessageBadgeUpdateService messageBadgeUpdateService,
            AppUserService appUserService) {
        this.securityService = securityService;
        this.userInvoiceDataService = userInvoiceDataService;
        this.messageService = messageService;
        this.messageBadgeUpdateService = messageBadgeUpdateService;
        this.appUserService = appUserService;
        setPrimarySection(Section.DRAWER);

        // Always build the drawer; keep references and toggle visibility on attach and
        // after navigation
        headerRef = createHeader();
        navRef = new Scroller(createSideNav());
        userMenuRef = createUserMenu();
        addToDrawer(headerRef, navRef, userMenuRef);

        updateDrawerVisibility();

        // Re-check on attach (new UI/session) and on every navigation cycle
        addAttachListener(e -> updateDrawerVisibility());
    }

    private void updateDrawerVisibility() {
        boolean loggedIn = securityService.isUserLoggedIn();
        if (headerRef != null)
            headerRef.setVisible(loggedIn);
        if (navRef != null)
            navRef.setVisible(loggedIn);
        if (userMenuRef != null)
            userMenuRef.setVisible(loggedIn);
        setDrawerOpened(loggedIn);
    }

    private Div createHeader() {
        var appLogo = VaadinIcon.CUBES.create();
        appLogo.addClassNames(TextColor.PRIMARY, IconSize.LARGE);

        var appName = new Span("VotianLT");
        appName.addClassNames(FontWeight.SEMIBOLD, FontSize.LARGE);

        var header = new Div(appLogo, appName);
        header.addClassNames(Display.FLEX, Padding.MEDIUM, Gap.MEDIUM, AlignItems.CENTER);
        return header;
    }

    private Component createSideNav() {
        var nav = new SideNav();
        nav.addClassNames(Margin.Horizontal.MEDIUM);

        MenuConfiguration.getMenuEntries().forEach(entry -> {
            // Skip "Verwaltung" entry as we'll handle it separately with Details component
            if (!"Verwaltung".equals(entry.title())) {
                SideNavItem item = createSideNavItem(entry);
                nav.addItem(item);
            }
        });

        // Create Details component for "Verwaltung" with collapsible list
        Details verwaltungDetails = new Details();
        verwaltungDetails.setSummaryText("Verwaltung");
        verwaltungDetails.addClassNames(Margin.Horizontal.MEDIUM, FontSize.MEDIUM, FontWeight.MEDIUM, "#000000");

        // Create collapsible content with navigation items
        VerticalLayout verwaltungContent = new VerticalLayout();
        verwaltungContent.setPadding(false);
        verwaltungContent.setSpacing(true);

        // Create navigation items for the collapsible list
        SideNavItem jobs = new SideNavItem("Aufträge", "jobs", new Icon(VaadinIcon.LIST));
        SideNavItem customers = new SideNavItem("Kunden", "customers", new Icon(VaadinIcon.USERS));
        SideNavItem appUsers = new SideNavItem("App-Nutzer", "app-user", new Icon(VaadinIcon.USERS));
        SideNavItem statistics = new SideNavItem("Statistiken", "statistics", new Icon(VaadinIcon.BAR_CHART));

        verwaltungContent.add(jobs, customers, appUsers);

        // Only show invoices menu if billing is enabled for the current user
        if (isBillingEnabledForCurrentUser()) {
            SideNavItem invoices = new SideNavItem("Rechnungen", "invoices", new Icon(VaadinIcon.FILE_TEXT));
            verwaltungContent.add(invoices);
        }

        verwaltungContent.add(statistics);
        verwaltungDetails.add(verwaltungContent);

        // Create Details component for "Verwaltung" with collapsible list
        Details userDetails = new Details();
        userDetails.setSummaryText("Benutzer");
        userDetails.addClassNames(Margin.Horizontal.MEDIUM, FontSize.MEDIUM, FontWeight.MEDIUM, TextColor.BODY);

        // Create collapsible content with navigation items
        VerticalLayout userContent = new VerticalLayout();
        userContent.setPadding(false);
        userContent.setSpacing(true);

        // Create navigation items for the collapsible list
        SideNavItem profile = new SideNavItem("Mein Profil", "edit-profile", new Icon(VaadinIcon.USER));
        SideNavItem myInvoices = new SideNavItem("Meine Rechnungen", "my-invoices", new Icon(VaadinIcon.FILE_TEXT));
        SideNavItem imprint = new SideNavItem("Impressum", "impressum", new Icon(VaadinIcon.INFO_CIRCLE));

        userContent.add(profile, myInvoices, imprint);
        userDetails.add(userContent);

        // Create a vertical layout to hold both regular menu items and collapsible
        // sections
        VerticalLayout navContainer = new VerticalLayout();
        navContainer.setPadding(false);
        navContainer.setSpacing(false);
        navContainer.add(nav, verwaltungDetails, userDetails);

        return navContainer;
    }

    private SideNavItem createSideNavItem(MenuEntry menuEntry) {
        SideNavItem item;
        if (menuEntry.icon() != null) {
            item = new SideNavItem(menuEntry.title(), menuEntry.path(), new Icon(menuEntry.icon()));
        } else {
            item = new SideNavItem(menuEntry.title(), menuEntry.path());
        }
        if ("Nachrichten".equals(menuEntry.title())) {
            messagesNavItem = item;
        }
        return item;
    }

    /**
     * Updates the messages badge with the current unread count
     */
    private void updateMessagesBadge() {
        if (messagesNavItem == null) {
            return;
        }

        long unreadCount = resolveUnreadMessageCount();

        if (unreadCount > 0) {
            if (messagesBadge == null) {
                messagesBadge = new Span(String.valueOf(unreadCount));
                messagesBadge.getElement().getThemeList().add("badge");
                messagesBadge.getStyle().set("background-color", "var(--lumo-primary-color)");
                messagesBadge.getStyle().set("color", "#ffffff");
                messagesBadge.getStyle().set("border-radius", "12px");
                messagesBadge.getStyle().set("padding", "2px 8px");
                messagesBadge.getStyle().set("font-size", "12px");
                messagesBadge.getStyle().set("font-weight", "bold");
                messagesBadge.getStyle().set("min-width", "20px");
                messagesBadge.getStyle().set("text-align", "center");
                messagesNavItem.setSuffixComponent(messagesBadge);
            } else {
                messagesBadge.setText(String.valueOf(unreadCount));
                messagesBadge.setVisible(true);
            }
        } else {
            if (messagesBadge != null) {
                messagesNavItem.setSuffixComponent(null);
                messagesBadge = null;
            }
        }
    }

    private long resolveUnreadMessageCount() {
        if (!securityService.isUserLoggedIn()) {
            return 0;
        }

        try {
            // Get all AppUsers for the current user
            List<de.assecutor.votianlt.model.AppUser> appUsers = appUserService.findByCurrentUser();

            if (appUsers == null || appUsers.isEmpty()) {
                return 0;
            }

            // Count unread messages for all AppUsers (receiver = AppUser ID)
            long unread = 0;
            for (de.assecutor.votianlt.model.AppUser appUser : appUsers) {
                if (appUser != null && appUser.getId() != null) {
                    String appUserId = appUser.getId().toHexString();
                    unread += messageService.getUnreadMessageCount(appUserId);
                }
            }

            return unread;
        } catch (RuntimeException e) {
            log.error("Error resolving unread message count: {}", e.getMessage(), e);
            return 0;
        }
    }

    private Component createUserMenu() {
        var userMenu = new MenuBar();
        userMenu.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
        userMenu.addClassNames(Margin.MEDIUM);

        // Dynamisch aktualisierbare Komponenten
        var avatar = new Avatar();
        avatar.addThemeVariants(AvatarVariant.LUMO_XSMALL);
        avatar.addClassNames(Margin.Right.SMALL);
        avatar.setColorIndex(5);

        var userNameSpan = new Span();

        var userMenuItem = userMenu.addItem(avatar);
        userMenuItem.add(userNameSpan);

        // Profil anzeigen mit Navigation
        userMenuItem.getSubMenu().addItem("Profil anzeigen", e -> UI.getCurrent().navigate(EditProfileView.class));
        userMenuItem.getSubMenu().addItem("Einstellungen");
        userMenuItem.getSubMenu().addItem("Abmelden", e -> securityService.logout());

        // Update-Funktion für Benutzername und Avatar
        Runnable updateUserInfo = () -> {
            String currentUser = securityService.getCurrentUsername();
            avatar.setName(currentUser);
            userNameSpan.setText(currentUser);
        };

        // Initial und bei Attach aktualisieren
        updateUserInfo.run();
        addAttachListener(e -> updateUserInfo.run());

        return userMenu;
    }

    private boolean isBillingEnabledForCurrentUser() {
        try {
            User currentUser = securityService.getCurrentDatabaseUser();
            if (currentUser != null && currentUser.getId() != null) {
                UserInvoiceData invoiceData = userInvoiceDataService.findByUserId(currentUser.getId()).orElse(null);
                return invoiceData != null && invoiceData.isBillingEnabled();
            }
        } catch (Exception e) {
            // Log error or handle appropriately
            // Return false as safe default if we can't determine billing status
        }
        return false;
    }

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        super.onAttach(attachEvent);
        UI ui = attachEvent.getUI();

        // Update badge immediately when layout is attached
        updateMessagesBadge();

        // Register listener for badge updates
        badgeUpdateRegistration = messageBadgeUpdateService.register(() -> {
            ui.access(() -> {
                updateMessagesBadge();
            });
        });
    }

    @Override
    protected void onDetach(DetachEvent detachEvent) {
        if (badgeUpdateRegistration != null) {
            badgeUpdateRegistration.remove();
            badgeUpdateRegistration = null;
        }
        super.onDetach(detachEvent);
    }
}