package de.effigenix.infrastructure.security;

import de.effigenix.domain.filiales.FilialesAction;
import de.effigenix.domain.inventory.InventoryAction;
import de.effigenix.domain.labeling.LabelingAction;
import de.effigenix.domain.procurement.ProcurementAction;
import de.effigenix.domain.production.ProductionAction;
import de.effigenix.domain.quality.QualityAction;
import de.effigenix.domain.sales.SalesAction;
import de.effigenix.domain.usermanagement.Permission;
import de.effigenix.domain.usermanagement.UserManagementAction;
import de.effigenix.shared.security.Action;
import org.springframework.stereotype.Component;

/**
 * Type-safe mapper from Bounded Context Actions to User Management Permissions.
 *
 * This is the Anti-Corruption Layer (ACL) between:
 * - Domain Language: BCs use their own Action enums (e.g., ProductionAction.RECIPE_WRITE)
 * - User Management: Uses granular Permissions (e.g., Permission.RECIPE_WRITE)
 *
 * Benefits:
 * - Type Safety: Compile-time checking for known action types
 * - Decoupling: BCs don't depend on Permission enum
 * - Future-Proof: Adding new BC actions requires updating this mapper
 * - Keycloak Migration: Can replace this with KeycloakActionMapper without BC changes
 *
 * Note: Cannot use sealed interfaces because Java requires all permitted classes
 * to be in the same package (unless using JPMS modules). Instead, we use instanceof
 * checks with enum switching for type safety.
 *
 * Example:
 * <pre>
 * Action action = ProductionAction.RECIPE_WRITE;
 * Permission permission = mapper.mapActionToPermission(action);
 * // permission == Permission.RECIPE_WRITE
 * </pre>
 *
 * Infrastructure Layer → Used by SpringSecurityAuthorizationAdapter
 */
@Component
public class ActionToPermissionMapper {

    /**
     * Maps a domain Action to a User Management Permission.
     *
     * Uses instanceof checks to determine the BC, then switches on the enum value.
     * While not compiler-enforced exhaustive like sealed interfaces, the enum switches
     * within each instanceof block provide compile-time safety for known enum values.
     *
     * @param action Type-safe action from a BC's Action enum
     * @return Corresponding Permission
     * @throws IllegalArgumentException if action is null or unknown type
     */
    public Permission mapActionToPermission(Action action) {
        if (action == null) {
            throw new IllegalArgumentException("Action cannot be null");
        }

        // Pattern matching with instanceof checks
        if (action instanceof ProductionAction productionAction) {
            return mapProductionAction(productionAction);
        } else if (action instanceof QualityAction qualityAction) {
            return mapQualityAction(qualityAction);
        } else if (action instanceof InventoryAction inventoryAction) {
            return mapInventoryAction(inventoryAction);
        } else if (action instanceof ProcurementAction procurementAction) {
            return mapProcurementAction(procurementAction);
        } else if (action instanceof SalesAction salesAction) {
            return mapSalesAction(salesAction);
        } else if (action instanceof LabelingAction labelingAction) {
            return mapLabelingAction(labelingAction);
        } else if (action instanceof FilialesAction filialesAction) {
            return mapFilialesAction(filialesAction);
        } else if (action instanceof UserManagementAction userMgmtAction) {
            return mapUserManagementAction(userMgmtAction);
        } else {
            throw new IllegalArgumentException("Unknown action type: " + action.getClass().getName());
        }
    }

    private Permission mapProductionAction(ProductionAction action) {
        return switch (action) {
            case RECIPE_READ -> Permission.RECIPE_READ;
            case RECIPE_WRITE -> Permission.RECIPE_WRITE;
            case RECIPE_DELETE -> Permission.RECIPE_DELETE;
            case BATCH_READ -> Permission.BATCH_READ;
            case BATCH_WRITE -> Permission.BATCH_WRITE;
            case BATCH_COMPLETE -> Permission.BATCH_COMPLETE;
            case BATCH_CANCEL -> Permission.BATCH_CANCEL;
            case BATCH_DELETE -> Permission.BATCH_DELETE;
            case PRODUCTION_ORDER_READ -> Permission.PRODUCTION_ORDER_READ;
            case PRODUCTION_ORDER_WRITE -> Permission.PRODUCTION_ORDER_WRITE;
            case PRODUCTION_ORDER_DELETE -> Permission.PRODUCTION_ORDER_DELETE;
        };
    }

    private Permission mapQualityAction(QualityAction action) {
        return switch (action) {
            case HACCP_READ -> Permission.HACCP_READ;
            case HACCP_WRITE -> Permission.HACCP_WRITE;
            case TEMPERATURE_LOG_READ -> Permission.TEMPERATURE_LOG_READ;
            case TEMPERATURE_LOG_WRITE -> Permission.TEMPERATURE_LOG_WRITE;
            case CLEANING_RECORD_READ -> Permission.CLEANING_RECORD_READ;
            case CLEANING_RECORD_WRITE -> Permission.CLEANING_RECORD_WRITE;
            case GOODS_INSPECTION_READ -> Permission.GOODS_INSPECTION_READ;
            case GOODS_INSPECTION_WRITE -> Permission.GOODS_INSPECTION_WRITE;
        };
    }

    private Permission mapInventoryAction(InventoryAction action) {
        return switch (action) {
            case STOCK_READ -> Permission.STOCK_READ;
            case STOCK_WRITE -> Permission.STOCK_WRITE;
            case STOCK_MOVEMENT_READ -> Permission.STOCK_MOVEMENT_READ;
            case STOCK_MOVEMENT_WRITE -> Permission.STOCK_MOVEMENT_WRITE;
            case INVENTORY_COUNT_READ -> Permission.INVENTORY_COUNT_READ;
            case INVENTORY_COUNT_WRITE -> Permission.INVENTORY_COUNT_WRITE;
        };
    }

    private Permission mapProcurementAction(ProcurementAction action) {
        return switch (action) {
            case PURCHASE_ORDER_READ -> Permission.PURCHASE_ORDER_READ;
            case PURCHASE_ORDER_WRITE -> Permission.PURCHASE_ORDER_WRITE;
            case PURCHASE_ORDER_DELETE -> Permission.PURCHASE_ORDER_DELETE;
            case GOODS_RECEIPT_READ -> Permission.GOODS_RECEIPT_READ;
            case GOODS_RECEIPT_WRITE -> Permission.GOODS_RECEIPT_WRITE;
            case SUPPLIER_READ -> Permission.SUPPLIER_READ;
            case SUPPLIER_WRITE -> Permission.SUPPLIER_WRITE;
            case SUPPLIER_DELETE -> Permission.SUPPLIER_DELETE;
        };
    }

    private Permission mapSalesAction(SalesAction action) {
        return switch (action) {
            case ORDER_READ -> Permission.ORDER_READ;
            case ORDER_WRITE -> Permission.ORDER_WRITE;
            case ORDER_DELETE -> Permission.ORDER_DELETE;
            case INVOICE_READ -> Permission.INVOICE_READ;
            case INVOICE_WRITE -> Permission.INVOICE_WRITE;
            case INVOICE_DELETE -> Permission.INVOICE_DELETE;
            case CUSTOMER_READ -> Permission.CUSTOMER_READ;
            case CUSTOMER_WRITE -> Permission.CUSTOMER_WRITE;
            case CUSTOMER_DELETE -> Permission.CUSTOMER_DELETE;
        };
    }

    private Permission mapLabelingAction(LabelingAction action) {
        return switch (action) {
            case LABEL_READ -> Permission.LABEL_READ;
            case LABEL_WRITE -> Permission.LABEL_WRITE;
            case LABEL_PRINT -> Permission.LABEL_PRINT;
        };
    }

    private Permission mapFilialesAction(FilialesAction action) {
        return switch (action) {
            case BRANCH_READ -> Permission.BRANCH_READ;
            case BRANCH_WRITE -> Permission.BRANCH_WRITE;
            case BRANCH_DELETE -> Permission.BRANCH_DELETE;
        };
    }

    private Permission mapUserManagementAction(UserManagementAction action) {
        return switch (action) {
            case USER_CREATE -> Permission.USER_WRITE;
            case USER_UPDATE -> Permission.USER_WRITE;
            case USER_LOCK -> Permission.USER_LOCK;
            case USER_UNLOCK -> Permission.USER_UNLOCK;
            case USER_VIEW -> Permission.USER_READ;
            case USER_LIST -> Permission.USER_READ;
            case ROLE_ASSIGN -> Permission.ROLE_ASSIGN;
            case ROLE_REMOVE -> Permission.ROLE_REMOVE;
            case PASSWORD_CHANGE -> Permission.USER_WRITE;
        };
    }
}
