import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import { JobDataSchema } from "./validation.js";
import { access, readFile } from "fs/promises";
//#region src/cron/persistence.ts
init_write_file_atomic();
init_logger();
const log = createLogger("CronPersistence");
const DEFAULT_JOBS_FILE = {
	jobs: [],
	version: 1
};
var CronPersistence = class {
	filePath;
	cache = null;
	dirty = false;
	saveTimeout = null;
	debounceMs = 500;
	constructor(filePath) {
		this.filePath = filePath;
	}
	/**
	* Initialize the storage file
	*/
	async initialize() {
		try {
			await access(this.filePath);
			await this.load();
		} catch {
			await this.save(DEFAULT_JOBS_FILE);
			log.info({ path: this.filePath }, "Created new jobs file");
		}
	}
	/**
	* Load jobs from disk (with caching)
	*/
	async load() {
		if (this.cache) return this.cache;
		try {
			const content = await readFile(this.filePath, "utf-8");
			const data = JSON.parse(content);
			if (!data.jobs || !Array.isArray(data.jobs)) {
				log.warn({ path: this.filePath }, "Cron jobs file invalid (missing jobs[]), resetting to empty");
				this.cache = DEFAULT_JOBS_FILE;
				return this.cache;
			}
			const valid = [];
			for (const j of data.jobs) {
				const r = JobDataSchema.safeParse(j);
				if (r.success) valid.push(r.data);
				else log.warn({
					jobId: j.id,
					issues: r.error.flatten()
				}, "Dropped invalid cron job");
			}
			if (valid.length !== data.jobs.length) {
				data.jobs = valid;
				data.version = (data.version ?? 1) + 1;
				this.cache = data;
				await this.writeToDisk(data);
				this.dirty = false;
				log.info({ count: valid.length }, "Persisted cron jobs after validation");
				return data;
			}
			this.cache = data;
			log.debug({ jobCount: data.jobs.length }, "Loaded jobs from disk");
			return data;
		} catch (error) {
			const em = error instanceof Error ? error.message : String(error);
			log.error({
				err: error,
				path: this.filePath,
				errorMessage: em
			}, `Failed to load cron jobs file: ${em}`);
			this.cache = DEFAULT_JOBS_FILE;
			return this.cache;
		}
	}
	/**
	* Save jobs to disk (debounced)
	*/
	async save(data) {
		this.cache = data;
		this.markDirty();
	}
	/**
	* Force immediate save (sync to disk)
	*/
	async flush() {
		if (!this.dirty || !this.cache) return;
		if (this.saveTimeout) {
			clearTimeout(this.saveTimeout);
			this.saveTimeout = null;
		}
		await this.writeToDisk(this.cache);
		this.dirty = false;
	}
	/**
	* Get all jobs
	*/
	async getJobs() {
		return (await this.load()).jobs;
	}
	/**
	* Get a single job by ID
	*/
	async getJob(id) {
		return (await this.getJobs()).find((j) => j.id === id) || null;
	}
	/**
	* Add a new job
	*/
	async addJob(job) {
		const data = await this.load();
		data.jobs.push(job);
		data.version++;
		await this.save(data);
	}
	/**
	* Update an existing job
	*/
	async updateJob(id, updates, options) {
		const data = await this.load();
		const index = data.jobs.findIndex((j) => j.id === id);
		if (index === -1) return false;
		const merged = {
			...data.jobs[index],
			...updates,
			updated_at: (/* @__PURE__ */ new Date()).toISOString()
		};
		if (options?.clearAgentId) delete merged.agentId;
		if (options?.clearWorkingDirectory) delete merged.workingDirectory;
		data.jobs[index] = merged;
		data.version++;
		await this.save(data);
		return true;
	}
	/**
	* Remove a job
	*/
	async removeJob(id) {
		const data = await this.load();
		const initialLength = data.jobs.length;
		data.jobs = data.jobs.filter((j) => j.id !== id);
		if (data.jobs.length === initialLength) return false;
		data.version++;
		await this.save(data);
		return true;
	}
	/** Atomic write (fsync + rename) via shared helper. */
	async writeToDisk(data) {
		await writeTextAtomic(this.filePath, JSON.stringify(data, null, 2));
		log.debug({ jobCount: data.jobs.length }, "Jobs saved to disk");
	}
	/**
	* Mark cache as dirty and schedule debounced save
	*/
	markDirty() {
		this.dirty = true;
		if (this.saveTimeout) clearTimeout(this.saveTimeout);
		this.saveTimeout = setTimeout(() => {
			this.flush().catch((err) => {
				const em = err instanceof Error ? err.message : String(err);
				log.error({
					err,
					path: this.filePath,
					errorMessage: em
				}, `Failed to save cron jobs file: ${em}`);
			});
		}, this.debounceMs);
	}
	/**
	* Clear cache (useful for testing)
	*/
	clearCache() {
		this.cache = null;
		this.dirty = false;
		if (this.saveTimeout) {
			clearTimeout(this.saveTimeout);
			this.saveTimeout = null;
		}
	}
};
//#endregion
export { CronPersistence };

//# sourceMappingURL=persistence.js.map