import "dotenv/config";
import path from "node:path";
import { existsSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { isAddress } from "viem";
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const DEFAULT_API_URL = "https://3sat.network";
const DEFAULT_RPC_URL = "https://sepolia-rollup.arbitrum.io/rpc";
const DEFAULT_CHAIN_ID = 421614;
const DEFAULT_SAT_TOKEN = "0x8Fe0e3557773B200995608a43691f3dE9B2e3Fda";
const DEFAULT_USDC_TOKEN = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d";
const DEFAULT_BOUNTY_MANAGER = "0x942b326B190d588fE1bb3931502f509c9f9eC767";
function boolFromEnv(name, fallback) {
    const value = process.env[name];
    if (value === undefined) {
        return fallback;
    }
    return ["1", "true", "yes", "y"].includes(value.toLowerCase());
}
function numberFromEnv(name, fallback) {
    const value = Number(process.env[name]);
    return Number.isFinite(value) && value > 0 ? value : fallback;
}
function integerFromEnv(name, fallback) {
    return Math.floor(numberFromEnv(name, fallback));
}
function addressFromEnv(name, fallback) {
    const value = process.env[name]?.trim() || fallback;
    if (!isAddress(value)) {
        throw new Error(name + " must be a valid contract address.");
    }
    return value;
}
function privateKeyFromEnv() {
    const raw = process.env.SOLVER_PRIVATE_KEY;
    if (!raw) {
        throw new Error("SOLVER_PRIVATE_KEY is required.");
    }
    const value = raw.startsWith("0x") ? raw : "0x" + raw;
    if (!/^0x[a-fA-F0-9]{64}$/.test(value)) {
        throw new Error("SOLVER_PRIVATE_KEY must be a 32-byte hex private key.");
    }
    return value;
}
function firstExisting(paths) {
    return paths.find((candidate) => existsSync(candidate));
}
export function defaultCryptoMiniSatPath() {
    const configured = process.env.CRYPTOMINISAT_PATH?.trim();
    if (configured) {
        return path.resolve(configured);
    }
    return firstExisting([path.join(rootDir, "bin", "cryptominisat5")]);
}
export function loadConfig() {
    const cryptoMiniSatPath = defaultCryptoMiniSatPath();
    if (!cryptoMiniSatPath) {
        throw new Error("CryptoMiniSat executable was not found. Put cryptominisat5 under bin/ or set CRYPTOMINISAT_PATH.");
    }
    return {
        rootDir,
        apiUrl: (process.env["3SAT_API_URL"] || DEFAULT_API_URL).replace(/\/+$/, ""),
        rpcUrl: process.env.RPC_URL || DEFAULT_RPC_URL,
        chainId: Number(process.env.CHAIN_ID || String(DEFAULT_CHAIN_ID)),
        solverPrivateKey: privateKeyFromEnv(),
        satToken: addressFromEnv("SAT_TOKEN_ADDRESS", DEFAULT_SAT_TOKEN),
        usdcToken: addressFromEnv("USDC_TOKEN_ADDRESS", DEFAULT_USDC_TOKEN),
        bountyManager: addressFromEnv("BOUNTY_MANAGER_ADDRESS", DEFAULT_BOUNTY_MANAGER),
        cryptoMiniSatPath,
        pollIntervalMs: numberFromEnv("POLL_INTERVAL_SECONDS", 60) * 1000,
        maxBountiesPerPoll: integerFromEnv("MAX_BOUNTIES_PER_POLL", 5),
        maxActiveJobs: integerFromEnv("MAX_ACTIVE_JOBS", 3),
        minCommitSecondsLeft: integerFromEnv("MIN_COMMIT_SECONDS_LEFT", 120),
        solveTimeoutMs: numberFromEnv("SOLVE_TIMEOUT_SECONDS", 600) * 1000,
        minRewardTokens: process.env.MIN_REWARD_TOKEN?.trim() || process.env.MIN_REWARD_3SAT?.trim() || "0",
        dryRun: boolFromEnv("DRY_RUN", false),
        runOnce: boolFromEnv("RUN_ONCE", false),
        allowCompetingSubmissions: boolFromEnv("ALLOW_COMPETING_SUBMISSIONS", false),
        waitForFinalization: boolFromEnv("WAIT_FOR_FINALIZATION", true),
        artifactDir: path.resolve(process.env.ARTIFACT_DIR || "data/artifacts"),
        stateFile: path.resolve(process.env.STATE_FILE || "data/solver-state.json"),
        logFile: path.resolve(process.env.LOG_FILE || "logs/solver-client.log")
    };
}
