package de.votian.web.view;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
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.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import de.votian.web.model.SessionData;
import de.votian.web.service.ParameterProvider;
import de.votian.web.service.RestClientService;

import java.util.LinkedHashMap;
import java.util.Map;

public class MainLayout extends AppLayout implements BeforeEnterObserver {

    private final SessionData sessionData;
    private final ParameterProvider parameterProvider;
    private final RestClientService restClient;

    public MainLayout(SessionData sessionData, ParameterProvider parameterProvider, RestClientService restClient) {
        this.sessionData = sessionData;
        this.parameterProvider = parameterProvider;
        this.restClient = restClient;
        createHeader();
        createDrawer();
    }

    private void createHeader() {
        H1 logo = new H1("Votian");
        logo.getStyle()
                .set("font-size", "var(--lumo-font-size-l)")
                .set("margin", "0")
                .set("color", "#1b12b9");

        Span userInfo = new Span();
        if (sessionData.isAuthenticated()) {
            userInfo.setText(sessionData.getDisplayName());
        }
        userInfo.getStyle().set("font-size", "var(--lumo-font-size-s)");

        Button logoutButton = new Button("Abmelden", VaadinIcon.SIGN_OUT.create(), e -> logout());
        logoutButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL);

        HorizontalLayout header = new HorizontalLayout(new DrawerToggle(), logo, userInfo, logoutButton);
        header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
        header.expand(userInfo);
        header.setWidthFull();
        header.setPadding(true);
        header.setSpacing(true);

        addToNavbar(header);
    }

    private void createDrawer() {
        SideNav nav = new SideNav();
        nav.addItem(new SideNavItem("Dashboard", DashboardView.class, VaadinIcon.DASHBOARD.create()));

        if (sessionData.canViewJobs()) {
            nav.addItem(new SideNavItem("Auftraege", JobListView.class, VaadinIcon.CLIPBOARD_TEXT.create()));
        }
        if (sessionData.isCourierUser() && sessionData.canViewInvoices()) {
            nav.addItem(new SideNavItem("Auftraege", CourierInvoiceView.class, VaadinIcon.CLIPBOARD_TEXT.create()));
        }
        if (sessionData.canViewDisposition()) {
            nav.addItem(new SideNavItem("Disposition", DispositionView.class, VaadinIcon.MAP_MARKER.create()));
        }
        if (canAccessTracking()) {
            nav.addItem(new SideNavItem("Tracking", TrackingView.class, VaadinIcon.MAP_MARKER.create()));
        }
        if (sessionData.canViewLonghaul()) {
            nav.addItem(new SideNavItem("Ferntouren", LonghaulView.class, VaadinIcon.GLOBE.create()));
        }
        if (sessionData.canViewGroupware()) {
            nav.addItem(new SideNavItem("Vertrieb", GroupwareView.class, VaadinIcon.CALENDAR_USER.create()));
        }
        if (sessionData.canViewGenericExports()) {
            nav.addItem(new SideNavItem("Datenexport", GenericExportWorkspaceView.class, VaadinIcon.DOWNLOAD_ALT.create()));
        }
        if (sessionData.canViewReports()) {
            nav.addItem(new SideNavItem("Berichte", ReportWorkspaceView.class, VaadinIcon.CLIPBOARD_PULSE.create()));
        }
        if (sessionData.canViewCommunication()) {
            nav.addItem(new SideNavItem("Kommunikation", CommunicationWorkspaceView.class, VaadinIcon.COMMENT.create()));
        }
        if (sessionData.canViewGeoOperations()) {
            nav.addItem(new SideNavItem("Karten/Adressen", GeoOperationsWorkspaceView.class, VaadinIcon.MAP_MARKER.create()));
        }
        if (sessionData.canViewCostCenters()) {
            nav.addItem(new SideNavItem("Kostenstellen", CostCenterView.class, VaadinIcon.MONEY.create()));
        }
        if (sessionData.canViewCustomers()) {
            nav.addItem(new SideNavItem("Kunden", CustomerListView.class, VaadinIcon.GROUP.create()));
        }
        if (sessionData.canViewCouriers()) {
            nav.addItem(new SideNavItem("Kuriere", CourierListView.class, VaadinIcon.CAR.create()));
        }
        if (sessionData.canViewEmployees()) {
            nav.addItem(new SideNavItem("Mitarbeiter", EmployeeListView.class, VaadinIcon.USER.create()));
        }
        if (sessionData.canViewStatistics()) {
            nav.addItem(new SideNavItem("Statistik", StatisticsView.class, VaadinIcon.CHART.create()));
        }
        if (!sessionData.isCourierUser() && sessionData.canViewInvoices()) {
            nav.addItem(new SideNavItem("Rechnungen", InvoiceOverviewView.class, VaadinIcon.INVOICE.create()));
        }
        if (sessionData.canManagePricing()) {
            nav.addItem(new SideNavItem("Preise", PricingView.class, VaadinIcon.COIN_PILES.create()));
        }
        if (sessionData.canManageHeadquarters()) {
            nav.addItem(new SideNavItem("Niederlassung", HeadquartersAdminView.class, VaadinIcon.BUILDING.create()));
            nav.addItem(new SideNavItem("Feiertage", PublicHolidayView.class, VaadinIcon.CALENDAR.create()));
            nav.addItem(new SideNavItem("Gruppen/Filter", GroupFilterAdminView.class, VaadinIcon.TAGS.create()));
        }
        if (sessionData.canManageMetaFields()) {
            nav.addItem(new SideNavItem("Formulare", MetaFieldAdminView.class, VaadinIcon.FORM.create()));
        }
        if (sessionData.canManageImports()) {
            nav.addItem(new SideNavItem("Importe", ImportView.class, VaadinIcon.UPLOAD.create()));
        }
        if (sessionData.canViewWarehouse()) {
            nav.addItem(new SideNavItem("Lager", WarehouseView.class, VaadinIcon.ARCHIVES.create()));
        }

        nav.addItem(new SideNavItem("Passwort", PasswordChangeView.class, VaadinIcon.LOCK.create()));

        VerticalLayout drawerContent = new VerticalLayout(nav);
        drawerContent.setSizeFull();
        drawerContent.setPadding(false);
        drawerContent.setSpacing(false);

        addToDrawer(drawerContent);
    }

    private void logout() {
        try {
            restClient.post("/auth/logout", Map.of(), LinkedHashMap.class);
        } catch (Exception ignored) {
        }
        sessionData.clear();
        UI.getCurrent().navigate(LoginView.class);
        UI.getCurrent().getPage().reload();
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        if (!sessionData.isAuthenticated()) {
            event.rerouteTo(LoginView.class);
            return;
        }
        if (!canAccessTarget(event.getNavigationTarget())) {
            event.rerouteTo(DashboardView.class);
        }
    }

    private boolean canAccessTarget(Class<?> target) {
        if (target == DashboardView.class || target == PasswordChangeView.class) {
            return true;
        }
        if (target == CourierInvoiceView.class) {
            return sessionData.isCourierUser() && sessionData.canViewInvoices();
        }
        if (target == JobListView.class) {
            return sessionData.canViewJobs();
        }
        if (target == JobDetailView.class) {
            return sessionData.canViewJobs();
        }
        if (target == JobBatchView.class) {
            return sessionData.canBatchJobs();
        }
        if (target == DispositionView.class) {
            return sessionData.canViewDisposition();
        }
        if (target == TrackingView.class) {
            return canAccessTracking();
        }
        if (target == LonghaulView.class) {
            return sessionData.canViewLonghaul();
        }
        if (target == GroupwareView.class) {
            return sessionData.canViewGroupware();
        }
        if (target == GenericExportWorkspaceView.class) {
            return sessionData.canViewGenericExports();
        }
        if (target == ReportWorkspaceView.class) {
            return sessionData.canViewReports();
        }
        if (target == CommunicationWorkspaceView.class) {
            return sessionData.canViewCommunication();
        }
        if (target == GeoOperationsWorkspaceView.class) {
            return sessionData.canViewGeoOperations();
        }
        if (target == CostCenterView.class) {
            return sessionData.canViewCostCenters();
        }
        if (target == CustomerListView.class || target == CustomerDetailView.class) {
            return sessionData.canViewCustomers();
        }
        if (target == CourierListView.class || target == CourierDetailView.class) {
            return sessionData.canViewCouriers();
        }
        if (target == EmployeeListView.class || target == EmployeeDetailView.class) {
            return sessionData.canViewEmployees();
        }
        if (target == StatisticsView.class) {
            return sessionData.canViewStatistics();
        }
        if (target == InvoiceOverviewView.class) {
            return !sessionData.isCourierUser() && sessionData.canViewInvoices();
        }
        if (target == PricingView.class) {
            return sessionData.canManagePricing();
        }
        if (target == HeadquartersAdminView.class) {
            return sessionData.canManageHeadquarters();
        }
        if (target == PublicHolidayView.class) {
            return sessionData.canManageHeadquarters();
        }
        if (target == GroupFilterAdminView.class) {
            return sessionData.canManageHeadquarters();
        }
        if (target == MetaFieldAdminView.class) {
            return sessionData.canManageMetaFields();
        }
        if (target == ImportView.class) {
            return sessionData.canManageImports();
        }
        if (target == WarehouseView.class) {
            return sessionData.canViewWarehouse();
        }
        return sessionData.isHeadquartersUser();
    }

    private boolean canAccessTracking() {
        if (sessionData.isHeadquartersUser()) {
            return sessionData.canViewDisposition() || sessionData.canViewJobs();
        }
        if (!sessionData.isCustomerUser() || !sessionData.canViewJobs() || sessionData.getCustomerId() == null) {
            return false;
        }
        return parameterProvider.isForObject("TRACKING_ENABLED_CS_", sessionData.getCustomerId())
                || parameterProvider.is("CS_TRACKING_ENABLED");
    }
}
