import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { StructuredError } from '@agentuity/core';
import { getAPIBaseURL } from '@agentuity/server';
import { z } from 'zod';
import { getUserAgent } from "../api.js";
import { getDefaultConfigDir } from "../config.js";
import { pathExists } from "../node-compat/fs.js";
const AptValidationError = StructuredError('AptValidationError');
const AptValidationAPIError = StructuredError('AptValidationAPIError')();
const AptValidationResponseError = StructuredError('AptValidationResponseError')();
const InvalidPackageSchema = z.object({
    package: z.string(),
    error: z.string(),
    requestedVersion: z.string().optional(),
    availableVersions: z.array(z.string()).optional(),
    searchUrl: z.string(),
});
const ValidateAptDependenciesResponseSchema = z.object({
    success: z.boolean(),
    data: z
        .object({
        valid: z.array(z.string()),
        invalid: z.array(InvalidPackageSchema),
    })
        .optional(),
    message: z.string().optional(),
});
const REQUEST_TIMEOUT_MS = 30000; // 30 seconds client-side timeout
const CacheEntrySchema = z.object({
    timestamp: z.number(),
});
const ValidationCacheSchema = z.object({
    version: z.number(),
    entries: z.record(z.string(), CacheEntrySchema),
});
const CACHE_VERSION = 1;
const CACHE_TTL_MS = 90 * 24 * 60 * 60 * 1000; // 90 days
function getCachePath() {
    return join(getDefaultConfigDir(), 'dependency-validation.json');
}
async function loadCache(logger) {
    const cachePath = getCachePath();
    try {
        if (await pathExists(cachePath)) {
            const content = JSON.parse(await readFile(cachePath, 'utf-8'));
            const parsed = ValidationCacheSchema.safeParse(content);
            if (parsed.success && parsed.data.version === CACHE_VERSION) {
                return parsed.data;
            }
            logger.debug('Cache invalid or version mismatch, starting fresh');
        }
    }
    catch (err) {
        logger.debug('Failed to load validation cache: %s', err);
    }
    return { version: CACHE_VERSION, entries: {} };
}
async function saveCache(cache, logger) {
    const cachePath = getCachePath();
    try {
        await mkdir(dirname(cachePath), { recursive: true });
        await writeFile(cachePath, JSON.stringify(cache, null, 2));
    }
    catch (err) {
        logger.debug('Failed to save validation cache: %s', err);
    }
}
function isCacheEntryValid(entry) {
    return Date.now() - entry.timestamp < CACHE_TTL_MS;
}
/**
 * Validate apt dependencies against the Debian package repository.
 * Uses a local cache to avoid redundant API calls.
 * Calls the app API which checks packages against snapshot.debian.org.
 */
export async function validateAptDependencies(packages, region, config, logger) {
    if (packages.length === 0) {
        return { valid: [], invalid: [] };
    }
    const cache = await loadCache(logger);
    const now = Date.now();
    const cachedValid = [];
    const uncachedPackages = [];
    // Check cache for each package (only valid packages are cached)
    for (const pkg of packages) {
        const entry = cache.entries[pkg];
        if (entry && isCacheEntryValid(entry)) {
            cachedValid.push(pkg);
            logger.debug('Cache hit (valid): %s', pkg);
        }
        else {
            uncachedPackages.push(pkg);
            logger.debug('Cache miss: %s', pkg);
        }
    }
    // If all packages are cached, return immediately
    if (uncachedPackages.length === 0) {
        logger.debug('All %d packages found in cache', packages.length);
        return { valid: cachedValid, invalid: [] };
    }
    logger.debug('Validating %d uncached packages (%d cached)', uncachedPackages.length, packages.length - uncachedPackages.length);
    const apiBaseUrl = getAPIBaseURL(region, config?.overrides ?? undefined);
    const url = `${apiBaseUrl}/cli/validate/apt-dependencies`;
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'User-Agent': getUserAgent(config),
        },
        body: JSON.stringify({ packages: uncachedPackages }),
        signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
    });
    if (!response.ok) {
        const text = await response.text();
        throw new AptValidationAPIError({
            message: `Failed to validate apt dependencies: HTTP ${response.status}`,
            status: response.status,
            body: text,
        });
    }
    let json;
    try {
        json = await response.json();
    }
    catch (err) {
        throw new AptValidationResponseError({
            message: 'Invalid JSON in API response',
            parseError: err instanceof Error ? err.message : String(err),
        });
    }
    const parsed = ValidateAptDependenciesResponseSchema.safeParse(json);
    if (!parsed.success) {
        throw new AptValidationResponseError({
            message: 'Invalid API response structure',
            parseError: parsed.error.message,
        });
    }
    const result = parsed.data;
    if (!result.success || !result.data) {
        throw new AptValidationError({
            message: result.message ?? 'Failed to validate apt dependencies',
        });
    }
    // Update cache with valid results only (don't cache invalid packages)
    for (const pkg of result.data.valid) {
        cache.entries[pkg] = { timestamp: now };
    }
    await saveCache(cache, logger);
    logger.debug('Apt validation complete: %d valid, %d invalid (from API)', result.data.valid.length, result.data.invalid.length);
    // Combine cached and fresh results
    return {
        valid: [...cachedValid, ...result.data.valid],
        invalid: result.data.invalid,
    };
}
//# sourceMappingURL=apt-validator.js.map