import { ConfigService } from '@nestjs/config';
import { KubernetesService } from '../../infrastructure/shared/services/kubernetes.service';
import { AppBuildEntity } from '../entities/app-build.entity';
import { ApplicationEntity } from '../../applications/entities/application.entity';
export declare const BUILD_NAMESPACE = "flui-build";
export declare const BUILD_RUNNER_IMAGE = "ghcr.io/dawit-io/flui-build-runner:railpack-0.22.2";
export declare const BUILD_CACHE_PVC_NAME = "flui-buildkit-cache";
interface BuildJobInfo {
    name: string;
    status: 'Running' | 'Pending' | 'Succeeded' | 'Failed' | 'Unknown';
    ageSecs: number;
    buildId: string | null;
    appSlug: string | null;
    purpose: string | null;
    cpuRequestMillicores: number;
    memoryRequestMiB: number;
}
interface BuildPodInfo {
    name: string;
    phase: string;
    ageSecs: number;
    buildId: string | null;
    appSlug: string | null;
    containers: Array<{
        name: string;
        ready: boolean;
        state: string;
    }>;
}
/** Total CPU request (millicores) for a single build Job (git-clone + railpack + buildkitd) */
export declare const BUILD_JOB_CPU_REQUEST = 800;
/** Total memory request (Mi) for a single build Job */
export declare const BUILD_JOB_MEMORY_REQUEST = 896;
export interface BuildJobConfig {
    build: AppBuildEntity;
    app: ApplicationEntity;
    repoOwner: string;
    repoName: string;
    githubToken: string;
    imageRef: string;
    noCache?: boolean;
    cloneUrl?: string;
    deployStrategy?: string;
    suggestedBuildCommand?: string;
    suggestedStartCommand?: string;
    dockerfileContent?: string;
}
export declare class BuildJobService {
    private readonly kubernetesService;
    private readonly configService;
    private readonly logger;
    constructor(kubernetesService: KubernetesService, configService: ConfigService);
    /**
     * Ensure the flui-build namespace exists with the correct PSA labels.
     * Uses server-side apply so labels are always patched even if namespace already exists.
     */
    ensureBuildNamespace(kubeconfig: string): Promise<void>;
    /**
     * Create or update the ghcr-push-secret in the flui-build namespace.
     * Contains:
     *   - dockerconfig: Docker config.json for ghcr.io authentication
     *   - github_token: plaintext token for git clone via HTTPS
     */
    ensureGhcrSecret(kubeconfig: string, githubUsername: string, githubToken: string): Promise<void>;
    /**
     * Ensure the flui-buildkit-cache PVC exists in the flui-build namespace.
     * Mounts at /var/lib/buildkit in the buildkitd container to persist BuildKit's
     * content-addressable store across Jobs. This covers all package manager caches
     * (pnpm, NuGet, Maven, Gradle, pip, etc.) via railpack's RUN --mount=type=cache directives.
     */
    ensureBuildCachePvc(kubeconfig: string): Promise<void>;
    /**
     * Delete the flui-buildkit-cache PVC. Used by cache-clear operations.
     * Deletion is permanent — the underlying volume data is wiped.
     */
    deleteBuildCachePvc(kubeconfig: string): Promise<void>;
    /**
     * Return metadata about the flui-buildkit-cache PVC from the Kubernetes API.
     * Returns null if the PVC does not exist.
     */
    getBuildCachePvcInfo(kubeconfig: string): Promise<{
        exists: boolean;
        phase: string | null;
        capacity: string | null;
        storageClass: string | null;
        createdAt: Date | null;
    }>;
    /**
     * Build the image reference for the build.
     * Format: ghcr.io/{githubUsername}/{appName}:{branch}-{shortSha}
     * appName is derived from appSlug stripping any trailing branch/random suffix
     * so the ghcr.io package name stays stable across branches and rebuilds.
     */
    buildImageRef(githubUsername: string, appSlug: string, commitSha?: string, branch?: string, suffix?: string): string;
    /**
     * Generate a DNS-safe K8s Job name from the app slug and commit SHA.
     * Ensures max 63 chars (K8s name limit).
     */
    buildJobName(appSlug: string, commitSha?: string, suffix?: string): string;
    /**
     * Apply the K3s build Job manifest to the cluster.
     * Returns the job name applied.
     */
    createBuildJob(kubeconfig: string, config: BuildJobConfig): Promise<string>;
    /**
     * Ensure the build runner image exists in ghcr.io.
     * If missing, bootstrap it by running a K8s Job that builds and pushes the image
     * using the same BuildKit infrastructure used for app builds.
     */
    ensureBuildRunnerImage(kubeconfig: string, githubUsername: string, githubToken: string): Promise<void>;
    /**
     * Check if the build runner image exists in the ghcr.io registry.
     * Uses the Docker Distribution API v2 with the user's GitHub token.
     */
    private checkBuildRunnerExists;
    /**
     * Build and push the build runner image by running a one-off K8s Job.
     * The Job writes the Dockerfile from an embedded template, then uses
     * BuildKit (already available in the cluster) to build and push it.
     */
    private bootstrapBuildRunnerImage;
    private httpsGetJson;
    private httpsHeadStatus;
    /**
     * Delete a K3s Job and its pods (best-effort cleanup on failure).
     */
    deleteJob(kubeconfig: string, jobName: string, buildId?: string): Promise<void>;
    /**
     * Poll until the build Job pod transitions to Running.
     * Streams K8s Events for the pod to onStatusLine so the frontend receives
     * live feedback (image pulls, container creation, etc.) during Pending.
     * Returns the pod name once running.
     */
    waitForPodRunning(kubeconfig: string, buildId: string, timeoutMs?: number, onStatusLine?: (line: string) => void): Promise<string>;
    /**
     * Poll the Job status until it succeeds or fails.
     * Returns true on success, throws on failure.
     */
    waitForJobCompletion(kubeconfig: string, jobName: string, timeoutMs?: number): Promise<void>;
    /**
     * List all Jobs and Pods in the flui-build namespace with status, age, and labels.
     *
     * Tolerates a missing namespace (returns empty lists) so that callers can
     * safely query diagnostic endpoints on clusters where the in-cluster build
     * agent has never run — e.g. when the master switch is disabled.
     */
    getNamespaceResources(kubeconfig: string): Promise<{
        jobs: BuildJobInfo[];
        pods: BuildPodInfo[];
    }>;
    /**
     * Returns true if the error came from the Kubernetes API indicating that
     * the target namespace (or a resource within it) does not exist.
     * Handles both the new `@kubernetes/client-node` v1 error shape
     * (`ApiException` with `.code`) and the legacy `.response.statusCode` shape.
     */
    private isNamespaceNotFoundError;
    /**
     * Delete stale Jobs and orphaned Pods from the flui-build namespace.
     * Stale = build is in a terminal DB state, or the resource is in a K8s terminal state.
     * @param activeBuilds Set of build IDs that are currently in-progress (should NOT be deleted).
     * @param olderThanMinutes If > 0, skip resources younger than this threshold.
     * @param dryRun If true, return what would be deleted without making changes.
     */
    cleanupStaleResources(kubeconfig: string, activeBuilds: Set<string>, olderThanMinutes: number, dryRun: boolean): Promise<{
        deletedJobs: string[];
        deletedPods: string[];
    }>;
    private isJobStale;
    private isPodStale;
    private deriveJobStatus;
    private deriveContainerState;
    private ageSeconds;
    private parseCpuMillicores;
    private parseMemoryMiB;
    private sleep;
}
export {};
