import { Env } from './env.js';
import { ErrorFactory } from '../exceptions/ZintrustError.js';
import { ZintrustLang } from '../lang/lang.js';
import { existsSync } from '../node-singletons/fs.js';
import * as path from '../node-singletons/path.js';
import { pathToFileURL } from '../node-singletons/url.js';
import { Queue } from '../tools/queue/Queue.js';
export const buildRedisUrl = (config) => {
    // Otherwise build URL from individual settings (like cache driver)
    const host = config?.host ?? Env.get('REDIS_HOST', 'localhost');
    const port = config?.port ?? Env.getInt('REDIS_PORT', ZintrustLang.REDIS_DEFAULT_PORT);
    const password = config?.password ?? Env.get('REDIS_PASSWORD');
    const database = config?.database ?? Env.getInt('REDIS_QUEUE_DB', ZintrustLang.REDIS_DEFAULT_DB);
    let redisUrl = `redis://`;
    if (password)
        redisUrl += `:${password}@`;
    redisUrl += `${host}:${port}`;
    if (database > 0)
        redisUrl += `/${database}`;
    return redisUrl;
};
export const getRedisUrl = (config) => {
    const fromEnv = Env.get('REDIS_URL', '');
    const hasProcess = typeof process === 'object' && process !== null;
    const fallback = hasProcess ? process.env?.['REDIS_URL'] ?? '' : '';
    const trimmed = fromEnv.trim();
    const url = (trimmed.length > 0 ? fromEnv : String(fallback)).trim();
    // If REDIS_URL exists, use it
    if (url.length > 0)
        return url;
    return buildRedisUrl(config);
};
const resolveLocalQueueRedisEntry = () => {
    const cwd = typeof process !== 'undefined' && typeof process.cwd === 'function' ? process.cwd() : '';
    if (cwd.trim() === '')
        return null;
    const localEntry = path.join(cwd, 'dist', 'packages', 'queue-redis', 'src', 'index.js');
    return existsSync(localEntry) ? localEntry : null;
};
const importQueueRedisModule = async () => {
    try {
        return (await import('@zintrust/queue-redis'));
    }
    catch {
        const localEntry = resolveLocalQueueRedisEntry();
        if (localEntry === null)
            return undefined;
        const url = pathToFileURL(localEntry).href;
        return (await import(url));
    }
};
const loadPluginDriver = async () => {
    try {
        const mod = await importQueueRedisModule();
        if (mod === undefined) {
            throw ErrorFactory.createConfigError('queue-redis package not found');
        }
        if (mod.RedisQueue !== undefined) {
            Queue.register('redis', mod.RedisQueue);
        }
        else if (mod.BullMQRedisQueue !== undefined) {
            Queue.register('redis', mod.BullMQRedisQueue);
        }
        return Queue.get('redis');
    }
    catch (error) {
        throw ErrorFactory.createConfigError('Redis queue driver is not registered. Install queue:redis via zin plugin install.', error);
    }
};
export const ensureDriver = async (type) => {
    if (type === 'publish') {
        // Return Redis publish client with publish() method from package
        const mod = await importQueueRedisModule();
        if (mod?.createRedisPublishClient) {
            return mod.createRedisPublishClient();
        }
        throw ErrorFactory.createConfigError('Redis publish client is not available in queue-redis package');
    }
    // Return queue driver (current behavior)
    try {
        const resolved = Queue.get('redis');
        if (!(resolved.__zintrustCoreRedisQueue ?? false)) {
            return resolved;
        }
        return await loadPluginDriver();
    }
    catch {
        return loadPluginDriver();
    }
};
