import { Stage } from '@layerzerolabs/lz-definitions'

import * as AddressConstants from './generated/addresses'
import { ObjectOptions, PackageOptions } from './types'

/**
 * Address mapping configuration for packages
 */
const PACKAGE_ADDRESS_MAP: { [K in keyof PackageOptions]: Partial<{ [S in Stage]: string }> } = {
    utils: AddressConstants.PACKAGE_UTILS_ADDRESS,
    endpointV2: AddressConstants.PACKAGE_ENDPOINT_V2_ADDRESS,
    counterV2: AddressConstants.PACKAGE_COUNTER_V2_ADDRESS,
    simpleMessageLib: AddressConstants.PACKAGE_SIMPLE_MESSAGE_LIB_ADDRESS,
    uln302: AddressConstants.PACKAGE_ULN_302_ADDRESS,
    uln302PtbBuilder: AddressConstants.PACKAGE_ULN_302_PTB_BUILDER_ADDRESS,
    blockedMessageLib: AddressConstants.PACKAGE_BLOCKED_MESSAGE_LIB_ADDRESS,
    blockedMessageLibPtbBuilder: AddressConstants.PACKAGE_BLOCKED_MESSAGE_LIB_PTB_BUILDER_ADDRESS,
    dvnPtbBuilder: AddressConstants.PACKAGE_DVN_PTB_BUILDER_ADDRESS,
    executorPtbBuilder: AddressConstants.PACKAGE_EXECUTOR_PTB_BUILDER_ADDRESS,
    executor: AddressConstants.PACKAGE_EXECUTOR_ADDRESS,
    zro: AddressConstants.PACKAGE_ZRO_ADDRESS,
    call: AddressConstants.PACKAGE_CALL_ADDRESS,
    endpointPtbBuilder: AddressConstants.PACKAGE_ENDPOINT_PTB_BUILDER_ADDRESS,
    simpleMessageLibPtbBuilder: AddressConstants.PACKAGE_SIMPLE_MESSAGE_LIB_PTB_BUILDER_ADDRESS,
    ptbMoveCall: AddressConstants.PACKAGE_PTB_MOVE_CALL_ADDRESS,
    dvn: AddressConstants.PACKAGE_DVN_ADDRESS,
    dvnFeeLib: AddressConstants.PACKAGE_DVN_FEE_LIB_ADDRESS,
    dvnLayerzero: AddressConstants.PACKAGE_DVN_LAYERZERO_ADDRESS,
    executorFeeLib: AddressConstants.PACKAGE_EXECUTOR_FEE_LIB_ADDRESS,
    executorLayerzero: AddressConstants.PACKAGE_EXECUTOR_LAYERZERO_ADDRESS,
    priceFeed: AddressConstants.PACKAGE_PRICE_FEED_ADDRESS,
    treasury: AddressConstants.PACKAGE_TREASURY_ADDRESS,
    oapp: AddressConstants.PACKAGE_OAPP_ADDRESS,
    layerzeroViews: AddressConstants.PACKAGE_LAYERZERO_VIEWS_ADDRESS,
    packageWhitelistValidator: AddressConstants.PACKAGE_PACKAGE_WHITELIST_VALIDATOR_ADDRESS,
    workerRegistry: AddressConstants.PACKAGE_WORKER_REGISTRY_ADDRESS,
    workerCommon: AddressConstants.PACKAGE_WORKER_COMMON_ADDRESS,
}

/**
 * Address mapping configuration for objects
 */
const OBJECT_ADDRESS_MAP: { [K in keyof ObjectOptions]: Partial<{ [S in Stage]: string }> } = {
    endpointV2: AddressConstants.OBJECT_ENDPOINT_V2_ADDRESS,
    simpleMessageLib: AddressConstants.OBJECT_SIMPLE_MESSAGE_LIB_ADDRESS,
    simpleMessageLibAdminCap: AddressConstants.OBJECT_SIMPLE_MESSAGE_LIB_ADMIN_CAP_ADDRESS,
    simpleMessageLibPtbBuilder: AddressConstants.OBJECT_SIMPLE_MESSAGE_LIB_PTB_BUILDER_ADDRESS,
    uln302: AddressConstants.OBJECT_ULN_302_ADDRESS,
    uln302AdminCap: AddressConstants.OBJECT_ULN_302_ADMIN_CAP_ADDRESS,
    uln302PtbBuilder: AddressConstants.OBJECT_ULN_302_PTB_BUILDER_ADDRESS,
    uln302Verification: AddressConstants.OBJECT_ULN_302_VERIFICATION_ADDRESS,
    treasury: AddressConstants.OBJECT_TREASURY_ADDRESS,
    treasuryAdminCap: AddressConstants.OBJECT_TREASURY_ADMIN_CAP_ADDRESS,
    blockedMessageLib: AddressConstants.OBJECT_BLOCKED_MESSAGE_LIB_ADDRESS,
    blockedMessageLibPtbBuilder: AddressConstants.OBJECT_BLOCKED_MESSAGE_LIB_PTB_BUILDER_ADDRESS,
    counter: AddressConstants.OBJECT_COUNTER_ADDRESS,
    counterOapp: AddressConstants.OBJECT_COUNTER_OAPP_ADDRESS,
    counterAdminCap: AddressConstants.OBJECT_COUNTER_ADMIN_CAP_ADDRESS,
    endpointAdminCap: AddressConstants.OBJECT_ENDPOINT_ADMIN_CAP_ADDRESS,
    endpointPtbBuilder: AddressConstants.OBJECT_ENDPOINT_PTB_BUILDER_ADDRESS,
    endpointPtbBuilderAdminCap: AddressConstants.OBJECT_ENDPOINT_PTB_BUILDER_ADMIN_CAP_ADDRESS,
    dvn: AddressConstants.OBJECT_DVN_ADDRESS,
    dvnCap: AddressConstants.OBJECT_DVN_CAP_ADDRESS,
    dvnFeeLib: AddressConstants.OBJECT_DVN_FEE_LIB_ADDRESS,
    executor: AddressConstants.OBJECT_EXECUTOR_ADDRESS,
    executorCap: AddressConstants.OBJECT_EXECUTOR_CAP_ADDRESS,
    executorOwnerCap: AddressConstants.OBJECT_EXECUTOR_OWNER_CAP_ADDRESS,
    executorFeeLib: AddressConstants.OBJECT_EXECUTOR_FEE_LIB_ADDRESS,
    priceFeed: AddressConstants.OBJECT_PRICE_FEED_ADDRESS,
    priceFeedOwnerCap: AddressConstants.OBJECT_PRICE_FEED_OWNER_CAP_ADDRESS,
    packageWhitelistValidator: AddressConstants.OBJECT_PACKAGE_WHITELIST_VALIDATOR_ADDRESS,
    workerRegistry: AddressConstants.OBJECT_WORKER_REGISTRY_ADDRESS,
}

/**
 * Simple Resource Manager for address resolution
 */
export class ResourceManager {
    /**
     * Build package configuration with address mappings for a given stage
     */
    static mergeDefaultPackageConfig(stage: Stage, customPackages?: Partial<PackageOptions>): PackageOptions {
        // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
        const config = {} as PackageOptions
        for (const [key, stageMap] of Object.entries(PACKAGE_ADDRESS_MAP)) {
            const typedKey = key as keyof PackageOptions
            config[typedKey] = stageMap[stage] ?? ''
        }
        return { ...config, ...customPackages }
    }

    /**
     * Build object configuration with address mappings for a given stage
     */
    static mergeDefaultObjectConfig(stage: Stage, customObjects?: Partial<ObjectOptions>): ObjectOptions {
        // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
        const config = {} as ObjectOptions
        for (const [key, stageMap] of Object.entries(OBJECT_ADDRESS_MAP)) {
            const typedKey = key as keyof ObjectOptions
            config[typedKey] = stageMap[stage] ?? ''
        }
        return { ...config, ...customObjects }
    }
}
