import { createHash } from "node:crypto";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { basename, join } from "node:path";
const DEFAULT_TASKS_BASE = join(homedir(), ".ezcoder", "tasks", "projects");
const LEGACY_TASKS_BASE = join(homedir(), ".ezcoder-tasks", "projects");
function tasksBase() {
    return process.env.EZCODER_TASKS_BASE ?? DEFAULT_TASKS_BASE;
}
function legacyTasksBase() {
    if (process.env.EZCODER_TASKS_BASE)
        return null;
    return process.env.GG_TASKS_BASE ?? LEGACY_TASKS_BASE;
}
export function taskProjectHash(cwd) {
    return createHash("sha256").update(cwd).digest("hex").slice(0, 16);
}
export function taskProjectDir(cwd, base = tasksBase()) {
    return join(base, taskProjectHash(cwd));
}
function tasksFilePath(cwd, base = tasksBase()) {
    return join(taskProjectDir(cwd, base), "tasks.json");
}
function metaFilePath(cwd, base = tasksBase()) {
    return join(taskProjectDir(cwd, base), "meta.json");
}
function normalizeTask(raw) {
    if (!raw.id || typeof raw.id !== "string")
        return null;
    const fallbackText = typeof raw.text === "string" ? raw.text : "Untitled task";
    const title = typeof raw.title === "string" && raw.title.trim() ? raw.title : fallbackText;
    const prompt = typeof raw.prompt === "string" && raw.prompt.trim() ? raw.prompt : title;
    const status = raw.status === "done" || raw.status === "in-progress" || raw.status === "pending"
        ? raw.status
        : "pending";
    const createdAt = typeof raw.createdAt === "string" && raw.createdAt.trim()
        ? raw.createdAt
        : new Date(0).toISOString();
    return {
        id: raw.id,
        title,
        prompt,
        ...(raw.text ? { text: raw.text } : {}),
        ...(raw.details ? { details: raw.details } : {}),
        status,
        createdAt,
    };
}
function parseTasks(data) {
    const raw = JSON.parse(data);
    if (!Array.isArray(raw))
        return [];
    return raw
        .map((item) => normalizeTask(item))
        .filter((item) => item !== null);
}
async function readTasksFromBase(cwd, base) {
    try {
        return parseTasks(await readFile(tasksFilePath(cwd, base), "utf-8"));
    }
    catch {
        return null;
    }
}
function readTasksFromBaseSync(cwd, base) {
    try {
        return parseTasks(readFileSync(tasksFilePath(cwd, base), "utf-8"));
    }
    catch {
        return null;
    }
}
async function writeTasksToBase(cwd, tasks, base) {
    const dir = taskProjectDir(cwd, base);
    await mkdir(dir, { recursive: true });
    await writeFile(tasksFilePath(cwd, base), JSON.stringify(tasks, null, 2) + "\n", "utf-8");
    await writeFile(metaFilePath(cwd, base), JSON.stringify({ path: cwd, name: basename(cwd) }, null, 2) + "\n", "utf-8");
}
function writeTasksToBaseSync(cwd, tasks, base) {
    const dir = taskProjectDir(cwd, base);
    mkdirSync(dir, { recursive: true });
    writeFileSync(tasksFilePath(cwd, base), JSON.stringify(tasks, null, 2) + "\n", "utf-8");
    writeFileSync(metaFilePath(cwd, base), JSON.stringify({ path: cwd, name: basename(cwd) }, null, 2) + "\n", "utf-8");
}
async function migrateLegacyTasksIfNeeded(cwd) {
    const legacyBase = legacyTasksBase();
    if (!legacyBase)
        return null;
    const targetFile = tasksFilePath(cwd);
    if (existsSync(targetFile))
        return null;
    const legacyTasks = await readTasksFromBase(cwd, legacyBase);
    if (!legacyTasks)
        return null;
    await writeTasksToBase(cwd, legacyTasks, tasksBase());
    return legacyTasks;
}
function migrateLegacyTasksIfNeededSync(cwd) {
    const legacyBase = legacyTasksBase();
    if (!legacyBase)
        return null;
    const targetFile = tasksFilePath(cwd);
    if (existsSync(targetFile))
        return null;
    const legacyTasks = readTasksFromBaseSync(cwd, legacyBase);
    if (!legacyTasks)
        return null;
    writeTasksToBaseSync(cwd, legacyTasks, tasksBase());
    return legacyTasks;
}
export async function loadTasks(cwd) {
    const tasks = await readTasksFromBase(cwd, tasksBase());
    if (tasks)
        return tasks;
    return (await migrateLegacyTasksIfNeeded(cwd)) ?? [];
}
export function loadTasksSync(cwd) {
    return readTasksFromBaseSync(cwd, tasksBase()) ?? migrateLegacyTasksIfNeededSync(cwd) ?? [];
}
export async function saveTasks(cwd, tasks) {
    await writeTasksToBase(cwd, tasks, tasksBase());
}
export function saveTasksSync(cwd, tasks) {
    writeTasksToBaseSync(cwd, tasks, tasksBase());
}
export function getTaskCount(cwd) {
    return loadTasksSync(cwd).filter((task) => task.status !== "done").length;
}
export function getNextPendingTask(cwd) {
    const pending = loadTasksSync(cwd).find((task) => task.status === "pending");
    if (!pending)
        return null;
    return {
        id: pending.id,
        title: pending.title,
        prompt: pending.prompt,
    };
}
export function markTaskInProgress(cwd, taskId) {
    const tasks = loadTasksSync(cwd);
    if (tasks.length === 0)
        return;
    const updated = tasks.map((task) => task.id === taskId ? { ...task, status: "in-progress" } : task);
    saveTasksSync(cwd, updated);
}
//# sourceMappingURL=task-store.js.map