package de.thpeetz.kontor.admin.views;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.admin.data.Permission;
import de.thpeetz.kontor.admin.data.Profile;
import de.thpeetz.kontor.admin.services.KontorUserDetailsService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = "admin/profile", layout = MainLayout.class)
@PageTitle("Profile | Admin | Kontor")
public class ProfileView extends VerticalLayout {

    Grid<Profile> grid = new Grid<>(Profile.class);
    TextField filterText = new TextField();
    ProfileForm form;
    KontorUserDetailsService service;

    @Autowired
    PasswordEncoder passwordEncoder;

    public ProfileView(KontorUserDetailsService service) {
        this.service = service;
        addClassName("profile-view");
        setSizeFull();
        configureGrid();
        configureForm();

        add(getToolbar(), getContent());
        updateList();
    }

    private void configureGrid() {
        grid.addClassName("profile-grid");
        grid.setSizeFull();
        grid.setColumns("userName", "email", "firstName", "lastName", "enabled");
        grid.getColumns().forEach(col -> col.setAutoWidth(true));
        grid.asSingleSelect().addValueChangeListener(event -> editProfile(event.getValue()));
    }

    private void configureForm() {
        form = new ProfileForm();
        form.setWidth("25em");
        form.setVisible(false);
        form.addSaveListener(this::saveProfile);
        form.addDeleteListener(this::deleteProfile);
        form.addCloseListener(e -> closeEditor());
    }

    private void saveProfile(ProfileForm.SaveEvent event) {
        Profile profile = event.getProfile();
        log.debug("ProfileView.saveProfile: {}", profile);
        List<Permission> permissions = form.permissionList.getSelectedItems().stream().collect(Collectors.toList());
        log.info("selected permissions: {}", permissions);
        if (form.hasPasswordChanged(profile)) {
            profile.setPassword(passwordEncoder.encode(profile.getPassword()));
            log.debug("password changed for profile {}", profile);
        }
        service.saveProfile(profile, permissions);
        updateList();
        closeEditor();
    }

    private void deleteProfile(ProfileForm.DeleteEvent event) {
        service.deleteProfile(event.getProfile());
        updateList();
        closeEditor();
    }

    private Component getContent() {
        HorizontalLayout content = new HorizontalLayout(grid, form);
        content.setFlexGrow(2, grid);
        content.setFlexGrow(1, form);
        content.addClassName("content");
        content.setSizeFull();
        return content;
    }

    private HorizontalLayout getToolbar() {
        filterText.setPlaceholder("Filter by user name...");
        filterText.setClearButtonVisible(true);
        filterText.setValueChangeMode(ValueChangeMode.LAZY);
        filterText.addValueChangeListener(e -> updateList());
        Button addProfileButton = new Button("Add profile", click -> addProfile());
        HorizontalLayout toolbar = new HorizontalLayout(filterText, addProfileButton);
        toolbar.addClassName("toolbar");
        return toolbar;
    }

    public void editProfile(Profile profile) {
        if (profile == null) {
            closeEditor();
        } else {
            form.setProfile(profile);
            form.setPermissions(service.findAllPermissions(), profile);
            form.setVisible(true);
            addClassName("editing");
        }
    }

    public void closeEditor() {
        form.setProfile(null);
        form.setVisible(false);
        removeClassName("editing");
    }

    private void addProfile() {
        grid.asSingleSelect().clear();
        editProfile(new Profile());
    }

    private void updateList() {
        grid.setItems(service.findAllProfiles(filterText.getValue()));
    }
}
