"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadConfig = loadConfig;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const defaultConfig = {
    baseUrl: 'http://localhost:3000',
    browser: 'chromium',
    headless: true,
    timeout: 30000,
    trace: true,
    screenshotOnFailure: true,
    viewport: {
        width: 1440,
        height: 900
    },
    resourcePaths: {
        payload: 'resources/1-payload',
        actual: 'resources/2-actual',
        expected: 'resources/3-expected',
        config: 'resources/4-config',
        input: 'resources/5-input',
        features: 'resources/features'
    },
    screenshots: {
        expectedDir: node_path_1.default.join('resources', '3-expected', 'screenshots'),
        actualDir: node_path_1.default.join('resources', '2-actual', 'screenshots'),
        diffDir: node_path_1.default.join('resources', '2-actual', 'screenshots-diff'),
        mode: 'compare',
        threshold: 0.1,
        maxDiffPixels: 0
    },
    credentials: {}
};
function loadConfig(cwd = process.cwd()) {
    const configPath = resolveConfigPath(cwd);
    const fileConfig = node_fs_1.default.existsSync(configPath)
        ? JSON.parse(stripByteOrderMark(node_fs_1.default.readFileSync(configPath, 'utf8')))
        : {};
    const resolvedSelectorFiles = loadSelectorCatalogs(cwd, fileConfig.selectorSources);
    const resourcePaths = {
        ...defaultConfig.resourcePaths,
        ...fileConfig.resourcePaths
    };
    const defaultScreenshots = {
        ...defaultConfig.screenshots,
        expectedDir: node_path_1.default.join(resourcePaths.expected, 'screenshots'),
        actualDir: node_path_1.default.join(resourcePaths.actual, 'screenshots'),
        diffDir: node_path_1.default.join(resourcePaths.actual, 'screenshots-diff')
    };
    return {
        ...defaultConfig,
        ...fileConfig,
        baseUrl: process.env.BDD_UI_BASE_URL ?? fileConfig.baseUrl ?? defaultConfig.baseUrl,
        browser: (process.env.BDD_UI_BROWSER ?? fileConfig.browser ?? defaultConfig.browser),
        headless: parseBoolean(process.env.BDD_UI_HEADLESS, fileConfig.headless ?? defaultConfig.headless),
        timeout: parseNumber(process.env.BDD_UI_TIMEOUT, fileConfig.timeout ?? defaultConfig.timeout),
        trace: parseBoolean(process.env.BDD_UI_TRACE, fileConfig.trace ?? defaultConfig.trace),
        screenshotOnFailure: parseBoolean(process.env.BDD_UI_SCREENSHOT_ON_FAILURE, fileConfig.screenshotOnFailure ?? defaultConfig.screenshotOnFailure),
        viewport: {
            width: fileConfig.viewport?.width ?? defaultConfig.viewport.width,
            height: fileConfig.viewport?.height ?? defaultConfig.viewport.height
        },
        resourcePaths,
        jsonComparison: fileConfig.jsonComparison,
        screenshots: {
            ...defaultScreenshots,
            ...fileConfig.screenshots
        },
        selectorSources: fileConfig.selectorSources,
        selectors: {
            ...resolvedSelectorFiles,
            ...fileConfig.selectors
        },
        credentials: fileConfig.credentials ?? defaultConfig.credentials,
        fieldVerification: fileConfig.fieldVerification,
        grids: fileConfig.grids,
        uiScanner: fileConfig.uiScanner,
        auth: fileConfig.auth
    };
}
function resolveConfigPath(cwd) {
    const override = process.env.BDD_UI_CONFIG_PATH;
    if (override) {
        return node_path_1.default.resolve(cwd, override);
    }
    const candidates = [
        node_path_1.default.join(cwd, defaultConfig.resourcePaths.config, 'bdd-ui.config.json'),
        node_path_1.default.join(cwd, 'bdd-ui.config.json')
    ];
    return candidates.find((candidate) => node_fs_1.default.existsSync(candidate)) ?? candidates[0];
}
function parseBoolean(value, fallback) {
    if (value === undefined) {
        return fallback;
    }
    return ['1', 'true', 'yes', 'y'].includes(value.toLowerCase());
}
function parseNumber(value, fallback) {
    if (value === undefined) {
        return fallback;
    }
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : fallback;
}
function stripByteOrderMark(value) {
    return value.charCodeAt(0) === 0xfeff ? value.slice(1) : value;
}
function loadSelectorCatalogs(cwd, selectorSources) {
    if (!selectorSources?.length) {
        return {};
    }
    const merged = {};
    for (const source of selectorSources) {
        for (const filePath of resolveSelectorSourcePaths(cwd, source)) {
            const selectors = JSON.parse(stripByteOrderMark(node_fs_1.default.readFileSync(filePath, 'utf8')));
            Object.assign(merged, selectors);
        }
    }
    return merged;
}
function resolveSelectorSourcePaths(cwd, source) {
    const normalized = source.replace(/\\/g, '/');
    if (!normalized.includes('*')) {
        const absolutePath = node_path_1.default.resolve(cwd, source);
        return node_fs_1.default.existsSync(absolutePath) ? [absolutePath] : [];
    }
    const root = resolveGlobRoot(cwd, normalized);
    if (!node_fs_1.default.existsSync(root)) {
        return [];
    }
    const regex = globToRegExp(normalized);
    return walkFiles(root)
        .filter((filePath) => regex.test(node_path_1.default.relative(cwd, filePath).split(node_path_1.default.sep).join('/')))
        .sort();
}
function resolveGlobRoot(cwd, pattern) {
    const wildcardIndex = pattern.search(/[*]/);
    const staticPrefix = wildcardIndex === -1 ? pattern : pattern.slice(0, wildcardIndex);
    const trimmedPrefix = staticPrefix.endsWith('/') ? staticPrefix.slice(0, -1) : staticPrefix;
    return node_path_1.default.resolve(cwd, trimmedPrefix || '.');
}
function walkFiles(rootPath) {
    const pending = [rootPath];
    const files = [];
    while (pending.length > 0) {
        const current = pending.shift();
        const stats = node_fs_1.default.statSync(current);
        if (stats.isDirectory()) {
            for (const entry of node_fs_1.default.readdirSync(current, { withFileTypes: true })) {
                pending.push(node_path_1.default.join(current, entry.name));
            }
            continue;
        }
        files.push(current);
    }
    return files;
}
function globToRegExp(pattern) {
    const escaped = pattern
        .replace(/[.+^${}()|[\]\\]/g, '\\$&')
        .replace(/\*\*/g, '::DOUBLE_STAR::')
        .replace(/\*/g, '[^/]*')
        .replace(/::DOUBLE_STAR::/g, '.*');
    return new RegExp(`^${escaped}$`);
}
