/**
 * Task Routes Module
 * CCW Loop System - HTTP API endpoints for Task management
 * Reference: .workflow/.scratchpad/loop-system-complete-design-20260121.md section 6.1
 */
import { join } from 'path';
import { readdir, readFile, writeFile } from 'fs/promises';
import { existsSync } from 'fs';
/**
 * Handle task routes
 * @returns true if route was handled, false otherwise
 */
export async function handleTaskRoutes(ctx) {
    const { pathname, req, res, initialPath, handlePostRequest } = ctx;
    // Get workflow directory from initialPath
    const workflowDir = initialPath || process.cwd();
    const taskDir = join(workflowDir, '.task');
    // GET /api/tasks - List all tasks
    if (pathname === '/api/tasks' && req.method === 'GET') {
        try {
            // Ensure task directory exists
            if (!existsSync(taskDir)) {
                res.writeHead(200, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ success: true, data: [], total: 0 }));
                return true;
            }
            // Read all task files
            const files = await readdir(taskDir);
            const taskFiles = files.filter(f => f.endsWith('.json'));
            const tasks = [];
            for (const file of taskFiles) {
                try {
                    const filePath = join(taskDir, file);
                    const content = await readFile(filePath, 'utf-8');
                    const task = JSON.parse(content);
                    tasks.push(task);
                }
                catch (error) {
                    // Skip invalid task files
                    console.error('Failed to read task file ' + file + ':', error);
                }
            }
            // Parse query parameters
            const url = new URL(req.url || '', `http://localhost`);
            const loopOnly = url.searchParams.get('loop_only') === 'true';
            const filterStatus = url.searchParams.get('filter'); // active | completed
            // Apply filters
            let filteredTasks = tasks;
            // Filter by loop_control.enabled
            if (loopOnly) {
                filteredTasks = filteredTasks.filter(t => t.loop_control?.enabled);
            }
            // Filter by status
            if (filterStatus) {
                filteredTasks = filteredTasks.filter(t => t.status === filterStatus);
            }
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                success: true,
                data: filteredTasks,
                total: filteredTasks.length,
                timestamp: new Date().toISOString()
            }));
            return true;
        }
        catch (error) {
            res.writeHead(500, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                success: false,
                error: error.message
            }));
            return true;
        }
    }
    // POST /api/tasks - Create new task
    if (pathname === '/api/tasks' && req.method === 'POST') {
        handlePostRequest(req, res, async (body) => {
            const task = body;
            // Validate required fields
            if (!task.id) {
                return { success: false, error: 'Task ID is required', status: 400 };
            }
            // Sanitize taskId to prevent path traversal
            if (task.id.includes('/') || task.id.includes('\\') || task.id === '..' || task.id === '.') {
                return { success: false, error: 'Invalid task ID format', status: 400 };
            }
            if (!task.loop_control) {
                return { success: false, error: 'loop_control is required', status: 400 };
            }
            if (!task.loop_control.enabled) {
                return { success: false, error: 'loop_control.enabled must be true', status: 400 };
            }
            if (!task.loop_control.cli_sequence || task.loop_control.cli_sequence.length === 0) {
                return { success: false, error: 'cli_sequence must contain at least one step', status: 400 };
            }
            try {
                // Ensure task directory exists
                const { mkdir } = await import('fs/promises');
                if (!existsSync(taskDir)) {
                    await mkdir(taskDir, { recursive: true });
                }
                // Check if task already exists
                const taskPath = join(taskDir, task.id + '.json');
                if (existsSync(taskPath)) {
                    return { success: false, error: 'Task already exists: ' + task.id, status: 409 };
                }
                // Build complete task object
                const fullTask = {
                    id: task.id,
                    title: task.title || task.id,
                    description: task.description || task.loop_control?.description || '',
                    status: task.status || 'active',
                    meta: task.meta,
                    context: task.context,
                    loop_control: task.loop_control
                };
                // Write task file
                await writeFile(taskPath, JSON.stringify(fullTask, null, 2), 'utf-8');
                return {
                    success: true,
                    data: {
                        task: fullTask,
                        path: taskPath
                    }
                };
            }
            catch (error) {
                return { success: false, error: error.message, status: 500 };
            }
        });
        return true;
    }
    // GET /api/tasks/:taskId - Get single task
    const taskDetailMatch = pathname.match(/^\/api\/tasks\/([^\/]+)$/);
    if (taskDetailMatch && req.method === 'GET') {
        const taskId = decodeURIComponent(taskDetailMatch[1]);
        // Sanitize taskId to prevent path traversal
        if (taskId.includes('/') || taskId.includes('\\') || taskId === '..' || taskId === '.') {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: 'Invalid task ID format' }));
            return true;
        }
        try {
            const taskPath = join(taskDir, taskId + '.json');
            if (!existsSync(taskPath)) {
                res.writeHead(404, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ success: false, error: 'Task not found: ' + taskId }));
                return true;
            }
            const content = await readFile(taskPath, 'utf-8');
            const task = JSON.parse(content);
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                success: true,
                data: {
                    task: task
                }
            }));
            return true;
        }
        catch (error) {
            res.writeHead(500, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                success: false,
                error: error.message
            }));
            return true;
        }
    }
    // POST /api/tasks/validate - Validate task loop_control configuration
    if (pathname === '/api/tasks/validate' && req.method === 'POST') {
        handlePostRequest(req, res, async (body) => {
            const task = body;
            const errors = [];
            const warnings = [];
            // Validate loop_control
            if (!task.loop_control) {
                errors.push('loop_control is required');
            }
            else {
                // Check enabled flag
                if (typeof task.loop_control.enabled !== 'boolean') {
                    errors.push('loop_control.enabled must be a boolean');
                }
                // Check cli_sequence
                if (!task.loop_control.cli_sequence || !Array.isArray(task.loop_control.cli_sequence)) {
                    errors.push('loop_control.cli_sequence must be an array');
                }
                else if (task.loop_control.cli_sequence.length === 0) {
                    errors.push('loop_control.cli_sequence must contain at least one step');
                }
                else {
                    // Validate each step
                    task.loop_control.cli_sequence.forEach((step, index) => {
                        if (!step.step_id) {
                            errors.push(`Step ${index + 1}: step_id is required`);
                        }
                        if (!step.tool) {
                            errors.push(`Step ${index + 1}: tool is required`);
                        }
                        else if (!['gemini', 'qwen', 'codex', 'claude', 'bash'].includes(step.tool)) {
                            warnings.push(`Step ${index + 1}: unknown tool '${step.tool}'`);
                        }
                        if (!step.prompt_template && step.tool !== 'bash') {
                            errors.push(`Step ${index + 1}: prompt_template is required for non-bash steps`);
                        }
                    });
                }
                // Check max_iterations
                if (task.loop_control.max_iterations !== undefined) {
                    if (typeof task.loop_control.max_iterations !== 'number' || task.loop_control.max_iterations < 1) {
                        errors.push('loop_control.max_iterations must be a positive number');
                    }
                    if (task.loop_control.max_iterations > 100) {
                        warnings.push('max_iterations > 100 may cause long execution times');
                    }
                }
            }
            // Return validation result
            const isValid = errors.length === 0;
            return {
                success: true,
                data: {
                    valid: isValid,
                    errors,
                    warnings
                }
            };
        });
        return true;
    }
    // PUT /api/tasks/:taskId - Update existing task
    if (pathname.match(/^\/api\/tasks\/[^/]+$/) && req.method === 'PUT') {
        const taskId = pathname.split('/').pop();
        if (!taskId) {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: 'Task ID required' }));
            return true;
        }
        // Sanitize taskId to prevent path traversal
        if (taskId.includes('/') || taskId.includes('\\') || taskId === '..' || taskId === '.') {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: 'Invalid task ID format' }));
            return true;
        }
        handlePostRequest(req, res, async (body) => {
            const updates = body;
            const taskPath = join(taskDir, taskId + '.json');
            // Check if task exists
            if (!existsSync(taskPath)) {
                return { success: false, error: 'Task not found: ' + taskId, status: 404 };
            }
            try {
                // Read existing task
                const existingContent = await readFile(taskPath, 'utf-8');
                const existingTask = JSON.parse(existingContent);
                // Merge updates (preserve id)
                const updatedTask = {
                    ...existingTask,
                    ...updates,
                    id: existingTask.id // Prevent id change
                };
                // If loop_control is being updated, merge it properly
                if (updates.loop_control) {
                    updatedTask.loop_control = {
                        ...existingTask.loop_control,
                        ...updates.loop_control
                    };
                }
                // Write updated task
                await writeFile(taskPath, JSON.stringify(updatedTask, null, 2), 'utf-8');
                return {
                    success: true,
                    data: {
                        task: updatedTask,
                        path: taskPath
                    }
                };
            }
            catch (error) {
                return { success: false, error: error.message, status: 500 };
            }
        });
        return true;
    }
    // GET /api/tasks/:taskId - Get specific task
    if (pathname.match(/^\/api\/tasks\/[^/]+$/) && req.method === 'GET') {
        const taskId = pathname.split('/').pop();
        if (!taskId) {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: 'Task ID required' }));
            return true;
        }
        // Sanitize taskId to prevent path traversal
        if (taskId.includes('/') || taskId.includes('\\') || taskId === '..' || taskId === '.') {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: 'Invalid task ID format' }));
            return true;
        }
        try {
            const taskPath = join(taskDir, taskId + '.json');
            if (!existsSync(taskPath)) {
                res.writeHead(404, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ success: false, error: 'Task not found' }));
                return true;
            }
            const content = await readFile(taskPath, 'utf-8');
            const task = JSON.parse(content);
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: true, data: task }));
            return true;
        }
        catch (error) {
            res.writeHead(500, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ success: false, error: error.message }));
            return true;
        }
    }
    return false;
}
//# sourceMappingURL=task-routes.js.map