/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { randomBytes } from 'node:crypto';
import { join } from 'node:path';
import { appendJsonlFile, compact, dedupeById, readJsonlFile } from './file-writer.js';
import { profileOwner } from './orchestration-records.js';
import { appendTaskContext, projectKnowledgeExists } from './project-knowledge.js';
export function createTask(cwd, input) {
    const now = new Date().toISOString();
    const record = compact({
        id: input.id ?? nextTaskId(),
        kind: 'task',
        event: 'created',
        summary: input.summary,
        status: 'open',
        owner: input.profile ? profileOwner(input.profile) : undefined,
        mode: input.mode,
        roles: input.roles,
        declaredPhases: input.declaredPhases,
        phaseOverrides: input.phaseOverrides,
        createdAt: now,
        updatedAt: now,
        evidenceIds: input.evidenceIds ?? [],
    });
    appendTask(cwd, record);
    appendTaskToKnowledge(cwd, record);
    return record;
}
export function listTasks(cwd, options = {}) {
    const owner = options.profile ? profileOwner(options.profile) : undefined;
    const records = latestTasks(cwd)
        .filter((record) => options.status ? record.status === options.status : !['deleted', 'archived'].includes(record.status))
        .filter((record) => (owner ? record.owner === owner : true))
        .filter((record) => (options.mode ? record.mode === options.mode : true));
    return typeof options.limit === 'number' ? records.slice(-options.limit) : records;
}
export function getTask(cwd, id) {
    return latestTasks(cwd).find((record) => record.id === id);
}
export function claimTask(cwd, input) {
    return updateTask(cwd, input.id, {
        event: 'claimed',
        status: 'claimed',
        owner: input.profile ? profileOwner(input.profile) : undefined,
        evidenceIds: input.evidenceIds,
    });
}
export function completeTask(cwd, input) {
    return updateTask(cwd, input.id, {
        event: 'done',
        status: 'done',
        owner: input.profile ? profileOwner(input.profile) : undefined,
        evidenceIds: input.evidenceIds,
    });
}
export function patchTask(cwd, input) {
    const current = getTask(cwd, input.id);
    if (!current)
        throw new Error(`Task not found: ${input.id}`);
    const record = compact({
        ...current,
        event: 'updated',
        summary: input.summary ?? current.summary,
        owner: input.profile ? profileOwner(input.profile) : current.owner,
        updatedAt: new Date().toISOString(),
        evidenceIds: mergeIds(current.evidenceIds, input.evidenceIds),
    });
    appendTask(cwd, record);
    return record;
}
export function cancelTask(cwd, id, reason) {
    return updateTask(cwd, id, { event: 'cancelled', status: 'cancelled', reason });
}
export function blockTask(cwd, id, reason) {
    return updateTask(cwd, id, { event: 'blocked', status: 'blocked', reason });
}
const STATUS_TO_EVENT = {
    open: 'updated',
    claimed: 'claimed',
    done: 'done',
    cancelled: 'cancelled',
    blocked: 'blocked',
    deleted: 'deleted',
    archived: 'archived',
};
export function transitionTask(cwd, input) {
    const event = STATUS_TO_EVENT[input.status];
    return updateTask(cwd, input.id, {
        event,
        status: input.status,
        owner: input.profile ? profileOwner(input.profile) : undefined,
        evidenceIds: input.evidenceIds,
        reason: input.reason,
    });
}
export function deleteTask(cwd, id) {
    return updateTask(cwd, id, { event: 'deleted', status: 'deleted' });
}
export function archiveTask(cwd, id) {
    return updateTask(cwd, id, { event: 'archived', status: 'archived' });
}
export function updateTaskRecord(cwd, id, input) {
    const current = getTask(cwd, id);
    if (!current)
        throw new Error(`Task not found: ${id}`);
    const record = compact({
        ...current,
        event: 'updated',
        updatedAt: new Date().toISOString(),
        ...(input.phaseOverrides !== undefined ? { phaseOverrides: input.phaseOverrides } : {}),
        ...(input.roles !== undefined ? { roles: input.roles } : {}),
    });
    appendTask(cwd, record);
    return record;
}
export function taskStatePath(cwd) {
    return join(cwd, '.setup-agents', 'state', 'tasks.jsonl');
}
function updateTask(cwd, id, changes) {
    const current = getTask(cwd, id);
    if (!current)
        throw new Error(`Task not found: ${id}`);
    const record = compact({
        ...current,
        event: changes.event,
        status: changes.status,
        owner: changes.owner ?? current.owner,
        updatedAt: new Date().toISOString(),
        evidenceIds: mergeIds(current.evidenceIds, changes.evidenceIds),
        ...(changes.reason ? { reason: changes.reason } : {}),
    });
    appendTask(cwd, record);
    return record;
}
function latestTasks(cwd) {
    return dedupeById(readTaskLog(cwd));
}
function readTaskLog(cwd) {
    return readJsonlFile(taskStatePath(cwd));
}
function appendTask(cwd, record) {
    appendJsonlFile(taskStatePath(cwd), record);
}
function mergeIds(existing, next) {
    return [...new Set([...existing, ...(next ?? [])])];
}
function nextTaskId() {
    return `setup-agents-task-${Date.now()}-${randomBytes(4).toString('hex')}`;
}
function appendTaskToKnowledge(cwd, record) {
    if (!projectKnowledgeExists(cwd))
        return;
    const role = record.owner?.replace('setup-agents:', '');
    appendTaskContext(cwd, record.id, record.summary, role);
}
//# sourceMappingURL=task-state.js.map