package de.votian.web.model;

import com.vaadin.flow.spring.annotation.VaadinSessionScope;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@VaadinSessionScope
public class SessionData {

    private Long userId;
    private Long headquartersId;
    private Long employeeId;
    private Long customerId;
    private Long costCenterId;
    private Long courierId;
    private String userName;
    private String userFirstname;
    private String authToken;
    private String pendingTotpToken;
    private Integer userType;
    private String legacyRights;
    private List<Long> accessibleCostCenterIds = new ArrayList<>();
    private List<Long> rightIds = new ArrayList<>();
    private List<String> rightNames = new ArrayList<>();
    private boolean authenticated;

    public Long getUserId() { return userId; }
    public void setUserId(Long userId) { this.userId = userId; }
    public Long getHeadquartersId() { return headquartersId; }
    public void setHeadquartersId(Long headquartersId) { this.headquartersId = headquartersId; }
    public Long getEmployeeId() { return employeeId; }
    public void setEmployeeId(Long employeeId) { this.employeeId = employeeId; }
    public Long getCustomerId() { return customerId; }
    public void setCustomerId(Long customerId) { this.customerId = customerId; }
    public Long getCostCenterId() { return costCenterId; }
    public void setCostCenterId(Long costCenterId) { this.costCenterId = costCenterId; }
    public Long getCourierId() { return courierId; }
    public void setCourierId(Long courierId) { this.courierId = courierId; }
    public String getUserName() { return userName; }
    public void setUserName(String userName) { this.userName = userName; }
    public String getUserFirstname() { return userFirstname; }
    public void setUserFirstname(String userFirstname) { this.userFirstname = userFirstname; }
    public String getAuthToken() { return authToken; }
    public void setAuthToken(String authToken) { this.authToken = authToken; }
    public String getPendingTotpToken() { return pendingTotpToken; }
    public void setPendingTotpToken(String pendingTotpToken) { this.pendingTotpToken = pendingTotpToken; }
    public Integer getUserType() { return userType; }
    public void setUserType(Integer userType) { this.userType = userType; }
    public String getLegacyRights() { return legacyRights; }
    public void setLegacyRights(String legacyRights) { this.legacyRights = legacyRights; }
    public List<Long> getAccessibleCostCenterIds() { return accessibleCostCenterIds; }
    public void setAccessibleCostCenterIds(List<Long> accessibleCostCenterIds) {
        this.accessibleCostCenterIds = accessibleCostCenterIds != null ? new ArrayList<>(accessibleCostCenterIds) : new ArrayList<>();
    }
    public List<Long> getRightIds() { return rightIds; }
    public void setRightIds(List<Long> rightIds) {
        this.rightIds = rightIds != null ? new ArrayList<>(rightIds) : new ArrayList<>();
    }
    public List<String> getRightNames() { return rightNames; }
    public void setRightNames(List<String> rightNames) {
        this.rightNames = rightNames != null ? new ArrayList<>(rightNames) : new ArrayList<>();
    }
    public boolean isAuthenticated() { return authenticated; }
    public void setAuthenticated(boolean authenticated) { this.authenticated = authenticated; }

    public boolean isHeadquartersUser() { return Integer.valueOf(1).equals(userType); }
    public boolean isCustomerUser() { return Integer.valueOf(2).equals(userType); }
    public boolean isCourierUser() { return Integer.valueOf(3).equals(userType); }
    public boolean isWarehouseUser() { return Integer.valueOf(4).equals(userType); }
    public boolean hasCostCenterAccess(Long costCenterId) {
        return costCenterId == null || accessibleCostCenterIds.contains(costCenterId);
    }

    public boolean canViewCustomers() {
        return isHeadquartersUser() && hqRight(0);
    }

    public boolean canManageCustomers() {
        return canViewCustomers();
    }

    public boolean canViewCouriers() {
        return isHeadquartersUser() && hqRight(1);
    }

    public boolean canManageCouriers() {
        return canViewCouriers();
    }

    public boolean canViewEmployees() {
        if (isHeadquartersUser()) {
            return hqRight(3);
        }
        if (isCustomerUser()) {
            return true;
        }
        return false;
    }

    public boolean canManageEmployees() {
        if (isHeadquartersUser()) {
            return hqRight(3);
        }
        return isCustomerUser() && customerRight(2);
    }

    public boolean canManageEmployeeMatrixRights() {
        return isHeadquartersUser() && hqRight(3);
    }

    public boolean canManageEmployeeCostCenterMatrix() {
        if (isHeadquartersUser()) {
            return canManageEmployees();
        }
        return isCustomerUser() && customerRight(2) && customerRight(12);
    }

    public boolean canViewCostCenters() {
        if (isHeadquartersUser()) {
            return canViewCustomers();
        }
        return isCustomerUser() && customerRight(0);
    }

    public boolean canManageCostCenters() {
        if (isHeadquartersUser()) {
            return canManageCustomers();
        }
        return isCustomerUser() && customerRight(1);
    }

    public boolean canViewJobs() {
        if (isHeadquartersUser()) {
            return hqRight(4) || hqRight(7);
        }
        if (isCustomerUser()) {
            return customerRight(4);
        }
        return false;
    }

    public boolean canManageJobs() {
        if (isHeadquartersUser()) {
            return hqRight(7);
        }
        return isCustomerUser() && customerRight(4);
    }

    public boolean canBatchJobs() {
        return canManageJobs();
    }

    public boolean canExportJobs() {
        if (isHeadquartersUser()) {
            return canViewJobs() && hqRight(42);
        }
        return isCustomerUser() && canViewJobs() && customerRight(7);
    }

    public boolean canViewInvoices() {
        if (isHeadquartersUser()) {
            return hqRight(5);
        }
        if (isCustomerUser()) {
            return customerRight(5);
        }
        return isCourierUser();
    }

    public boolean canExportInvoices() {
        if (isHeadquartersUser()) {
            return hqRight(5);
        }
        if (isCustomerUser()) {
            return customerRight(7);
        }
        return isCourierUser();
    }

    public boolean canViewStatistics() {
        if (isHeadquartersUser()) {
            return hqRight(8);
        }
        return isCustomerUser() && customerRight(8);
    }

    public boolean canViewDisposition() {
        return isHeadquartersUser() && (hqRight(7) || hqRight(19));
    }

    public boolean canManageDisposition() {
        return isHeadquartersUser() && hqRight(7);
    }

    public boolean canViewLonghaul() {
        return isHeadquartersUser() && hqRight(10);
    }

    public boolean canManageLonghaul() {
        return canViewLonghaul();
    }

    public boolean canViewGroupware() {
        return isHeadquartersUser() && hqRight(11);
    }

    public boolean canManageGroupware() {
        return canViewGroupware();
    }

    public boolean canViewGenericExports() {
        if (isHeadquartersUser()) {
            return hqRight(6);
        }
        return isCustomerUser() && customerRight(7);
    }

    public boolean canManageGenericExports() {
        return canViewGenericExports();
    }

    public boolean canViewCustomerReports() {
        return isHeadquartersUser() && hqRight(16) && hqRight(0);
    }

    public boolean canViewCourierReports() {
        return isHeadquartersUser() && hqRight(16) && hqRight(1);
    }

    public boolean canViewProspectReports() {
        return canViewCustomerReports();
    }

    public boolean canViewReports() {
        return canViewCustomerReports() || canViewCourierReports() || canViewProspectReports();
    }

    public boolean canManageReports() {
        return canViewReports();
    }

    public boolean canViewConfidentialReports() {
        return isHeadquartersUser() && hqRight(10);
    }

    public boolean canManageCourierMessageGroups() {
        return isHeadquartersUser() && hqRight(1);
    }

    public boolean canManageDeviceMessages() {
        return isHeadquartersUser() && hqRight(4);
    }

    public boolean canManageTicker() {
        return isHeadquartersUser() && hqRight(18);
    }

    public boolean canManageNewsletter() {
        return isHeadquartersUser() && hqRight(17);
    }

    public boolean canViewCommunication() {
        return canManageCourierMessageGroups()
                || canManageDeviceMessages()
                || canManageTicker()
                || canManageNewsletter();
    }

    public boolean canManageCommunication() {
        return canViewCommunication();
    }

    public boolean canViewGlobalMap() {
        return isHeadquartersUser() && hqRight(19);
    }

    public boolean canViewSimilaritySearch() {
        return isHeadquartersUser() && (hqRight(0) || hqRight(1));
    }

    public boolean canManageAddressDirectory() {
        return isHeadquartersUser() && hqRight(2);
    }

    public boolean canManageTravelTimes() {
        return canManageAddressDirectory();
    }

    public boolean canViewGeoOperations() {
        return canViewGlobalMap()
                || canViewSimilaritySearch()
                || canManageAddressDirectory();
    }

    public boolean canManageGeoOperations() {
        return canViewGeoOperations();
    }

    public boolean canManagePricing() {
        return isHeadquartersUser() && hqRight(2) && hqRight(29);
    }

    public boolean canManageHeadquarters() {
        return isHeadquartersUser() && hqRight(2);
    }

    public boolean canManageMetaFields() {
        return canManageHeadquarters();
    }

    public boolean canManageImports() {
        return isHeadquartersUser() && (hqRight(15) || hqRight(22) || hqRight(23));
    }

    public boolean canManageEmployeeWarehouseConfig() {
        return isHeadquartersUser() && canManageEmployees();
    }

    public boolean canViewWarehouse() {
        return isWarehouseUser() || (isHeadquartersUser() && hqRight(14));
    }

    public boolean canEditOwnEmployeeAccount() {
        return isCustomerUser() && customerRight(10);
    }

    public boolean canViewEmployee(Long targetEmployeeId) {
        if (isHeadquartersUser()) {
            return canViewEmployees();
        }
        return isCustomerUser()
                && (canManageEmployees()
                || (employeeId != null && employeeId.equals(targetEmployeeId)));
    }

    public boolean canEditEmployee(Long targetEmployeeId) {
        if (isHeadquartersUser()) {
            return canManageEmployees();
        }
        return isCustomerUser()
                && (canManageEmployees()
                || ((employeeId != null && employeeId.equals(targetEmployeeId))
                && canEditOwnEmployeeAccount()));
    }

    public String getDisplayName() {
        return (userFirstname != null ? userFirstname : "") + " " + (userName != null ? userName : "");
    }

    public void clear() {
        userId = null;
        headquartersId = null;
        employeeId = null;
        customerId = null;
        costCenterId = null;
        courierId = null;
        userName = null;
        userFirstname = null;
        authToken = null;
        pendingTotpToken = null;
        userType = null;
        legacyRights = null;
        accessibleCostCenterIds = new ArrayList<>();
        rightIds = new ArrayList<>();
        rightNames = new ArrayList<>();
        authenticated = false;
    }

    private boolean hqRight(int index) {
        return legacyRight(index, true);
    }

    private boolean customerRight(int index) {
        return legacyRight(index, false);
    }

    private boolean legacyRight(int index, boolean defaultIfMissing) {
        if (index < 0) {
            return false;
        }
        if (legacyRights == null || legacyRights.isBlank()) {
            return defaultIfMissing;
        }
        return legacyRights.length() > index && legacyRights.charAt(index) == '1';
    }
}
