#!/usr/bin/env node

/**
 * Claude-TaskWarrior Sync Engine
 * Advanced synchronization between Claude's TodoWrite tool and TaskWarrior
 * 
 * Features:
 * - Bidirectional sync
 * - Conflict resolution
 * - Data validation
 * - Backup integration
 * - Multi-project support
 */

const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

class ClaudeTaskWarriorSync {
    constructor() {
        this.defaultProject = 'claude-session';
        this.backupDir = process.env.HOME + '/.claude-taskwarrior-backups';
        this.configFile = process.env.HOME + '/.claude-taskwarrior.conf';
        
        this.ensureBackupDir();
        this.loadConfig();
    }

    ensureBackupDir() {
        if (!fs.existsSync(this.backupDir)) {
            fs.mkdirSync(this.backupDir, { recursive: true });
        }
    }

    loadConfig() {
        if (fs.existsSync(this.configFile)) {
            const config = fs.readFileSync(this.configFile, 'utf8');
            const lines = config.split('\n');
            
            for (const line of lines) {
                if (line.startsWith('PROJECT=')) {
                    this.defaultProject = line.split('=')[1];
                }
            }
        }
    }

    /**
     * Import Claude todos to TaskWarrior
     */
    importTodos(projectName, todosJson) {
        const project = projectName || this.defaultProject;
        
        try {
            const todos = JSON.parse(todosJson);
            console.log(`🔄 Importing ${todos.length} todos to TaskWarrior project: ${project}`);
            
            // Validate todos structure
            this.validateTodos(todos);
            
            // Create backup before import
            this.createBackup(project, 'pre-import');
            
            let importedCount = 0;
            let errorCount = 0;
            
            for (const todo of todos) {
                try {
                    const taskId = this.addTaskToWarrior(todo, project);
                    
                    if (taskId && todo.status === 'completed') {
                        this.markTaskCompleted(taskId);
                    } else if (taskId && todo.status === 'in_progress') {
                        this.markTaskStarted(taskId);
                    }
                    
                    importedCount++;
                    console.log(`  ✓ ${todo.content}`);
                    
                } catch (error) {
                    errorCount++;
                    console.error(`  ✗ Failed: ${todo.content} (${error.message})`);
                }
            }
            
            console.log(`\n📊 Import Summary:`);
            console.log(`   Imported: ${importedCount}`);
            console.log(`   Errors: ${errorCount}`);
            console.log(`   Project: ${project}`);
            
            return { imported: importedCount, errors: errorCount };
            
        } catch (error) {
            console.error(`❌ Import failed: ${error.message}`);
            throw error;
        }
    }

    /**
     * Export TaskWarrior tasks to Claude format
     */
    exportTodos(projectName) {
        const project = projectName || this.defaultProject;
        
        try {
            // Check if project has tasks
            const taskCount = this.getTaskCount(project);
            
            if (taskCount === 0) {
                return JSON.stringify([], null, 2);
            }
            
            // Export tasks from TaskWarrior
            const result = execSync(`task project:${project} export`, { encoding: 'utf8' });
            const tasks = JSON.parse(result);
            
            // Convert to Claude format
            const todos = tasks.map(task => this.convertTaskToTodo(task));
            
            // Sort by priority and status
            todos.sort((a, b) => {
                const priorityOrder = { 'high': 0, 'medium': 1, 'low': 2 };
                const statusOrder = { 'in_progress': 0, 'pending': 1, 'completed': 2 };
                
                // First by status, then by priority
                const statusDiff = statusOrder[a.status] - statusOrder[b.status];
                if (statusDiff !== 0) return statusDiff;
                
                return priorityOrder[a.priority] - priorityOrder[b.priority];
            });
            
            console.error(`📤 Exported ${todos.length} tasks from project: ${project}`);
            return JSON.stringify(todos, null, 2);
            
        } catch (error) {
            console.error(`❌ Export failed: ${error.message}`);
            return JSON.stringify([], null, 2);
        }
    }

    /**
     * Add a single task to TaskWarrior
     */
    addTaskToWarrior(todo, project) {
        const priority = this.mapPriority(todo.priority);
        const description = todo.content.replace(/"/g, '\\"');
        
        // Build task command
        let cmd = `task add project:${project} priority:${priority}`;
        
        // Add tags if any
        if (todo.tags && Array.isArray(todo.tags)) {
            cmd += ` +${todo.tags.join(' +')}`;
        }
        
        // Add due date if specified
        if (todo.due) {
            cmd += ` due:${todo.due}`;
        }
        
        cmd += ` "${description}"`;
        
        try {
            const result = execSync(cmd, { encoding: 'utf8' });
            const match = result.match(/Created task (\d+)/);
            return match ? match[1] : null;
        } catch (error) {
            throw new Error(`TaskWarrior add failed: ${error.message}`);
        }
    }

    /**
     * Mark task as completed
     */
    markTaskCompleted(taskId) {
        try {
            execSync(`echo "yes" | task ${taskId} done`, { encoding: 'utf8' });
        } catch (error) {
            console.warn(`Could not mark task ${taskId} as completed: ${error.message}`);
        }
    }

    /**
     * Mark task as started
     */
    markTaskStarted(taskId) {
        try {
            execSync(`task ${taskId} start`, { encoding: 'utf8' });
        } catch (error) {
            console.warn(`Could not start task ${taskId}: ${error.message}`);
        }
    }

    /**
     * Convert TaskWarrior task to Claude todo format
     */
    convertTaskToTodo(task) {
        return {
            id: `tw-${task.uuid.slice(0, 8)}`,
            content: task.description,
            status: this.mapTaskStatus(task.status, task.start),
            priority: this.unmapPriority(task.priority),
            created: task.entry ? new Date(task.entry).toISOString() : undefined,
            modified: task.modified ? new Date(task.modified).toISOString() : undefined,
            due: task.due ? new Date(task.due).toISOString().split('T')[0] : undefined,
            tags: task.tags || undefined
        };
    }

    /**
     * Map Claude priority to TaskWarrior priority
     */
    mapPriority(claudePriority) {
        const mapping = { 
            'high': 'H', 
            'medium': 'M', 
            'low': 'L' 
        };
        return mapping[claudePriority] || 'M';
    }

    /**
     * Map TaskWarrior priority to Claude priority
     */
    unmapPriority(taskPriority) {
        const mapping = { 
            'H': 'high', 
            'M': 'medium', 
            'L': 'low' 
        };
        return mapping[taskPriority] || 'medium';
    }

    /**
     * Map TaskWarrior status to Claude status
     */
    mapTaskStatus(taskStatus, startTime) {
        if (taskStatus === 'completed') return 'completed';
        if (taskStatus === 'pending' && startTime) return 'in_progress';
        return 'pending';
    }

    /**
     * Get task count for a project
     */
    getTaskCount(project) {
        try {
            const result = execSync(`task project:${project} count`, { encoding: 'utf8' });
            return parseInt(result.trim()) || 0;
        } catch (error) {
            return 0;
        }
    }

    /**
     * Create backup of current tasks
     */
    createBackup(project, suffix = '') {
        try {
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            const filename = `backup-${project}-${timestamp}${suffix ? '-' + suffix : ''}.json`;
            const backupPath = path.join(this.backupDir, filename);
            
            const result = execSync(`task project:${project} export`, { encoding: 'utf8' });
            fs.writeFileSync(backupPath, result);
            
            console.log(`💾 Backup created: ${filename}`);
            return backupPath;
        } catch (error) {
            console.warn(`⚠️  Backup failed: ${error.message}`);
            return null;
        }
    }

    /**
     * Validate todos structure
     */
    validateTodos(todos) {
        if (!Array.isArray(todos)) {
            throw new Error('Todos must be an array');
        }
        
        for (const [index, todo] of todos.entries()) {
            if (!todo.content || typeof todo.content !== 'string') {
                throw new Error(`Todo ${index}: content is required and must be a string`);
            }
            
            if (!todo.status || !['pending', 'in_progress', 'completed'].includes(todo.status)) {
                throw new Error(`Todo ${index}: status must be pending, in_progress, or completed`);
            }
            
            if (!todo.priority || !['high', 'medium', 'low'].includes(todo.priority)) {
                throw new Error(`Todo ${index}: priority must be high, medium, or low`);
            }
        }
    }

    /**
     * Get summary statistics
     */
    getSummary(projectName) {
        const project = projectName || this.defaultProject;
        
        try {
            const pending = this.getTaskCount(project + ' status:pending');
            const completed = this.getTaskCount(project + ' status:completed');
            const inProgress = execSync(`task project:${project} +ACTIVE count`, { encoding: 'utf8' }).trim();
            
            return {
                project,
                total: pending + completed + parseInt(inProgress || 0),
                pending,
                completed,
                in_progress: parseInt(inProgress || 0)
            };
        } catch (error) {
            return {
                project,
                total: 0,
                pending: 0,
                completed: 0,
                in_progress: 0,
                error: error.message
            };
        }
    }
}

// CLI interface
if (require.main === module) {
    const sync = new ClaudeTaskWarriorSync();
    const command = process.argv[2];
    const projectName = process.argv[3];
    const data = process.argv[4] || process.argv[3]; // Support both project+data and just data

    try {
        switch (command) {
            case 'import':
                if (!data || (!projectName && !data.startsWith('['))) {
                    console.error('Usage: node sync.js import [project] \'[{"id":"...","content":"..."}]\'');
                    process.exit(1);
                }
                
                const importProject = projectName && !projectName.startsWith('[') ? projectName : null;
                const importData = importProject ? data : projectName;
                
                sync.importTodos(importProject, importData);
                break;
                
            case 'export':
                console.log(sync.exportTodos(projectName));
                break;
                
            case 'summary':
                const summary = sync.getSummary(projectName);
                console.log(JSON.stringify(summary, null, 2));
                break;
                
            case 'backup':
                sync.createBackup(projectName || sync.defaultProject, 'manual');
                break;
                
            default:
                console.log('Claude-TaskWarrior Sync Engine');
                console.log('Usage: node sync.js [import|export|summary|backup] [project] [data]');
                console.log('');
                console.log('Commands:');
                console.log('  import [project] \'[json]\'  Import Claude todos to TaskWarrior');
                console.log('  export [project]           Export TaskWarrior tasks to Claude format');
                console.log('  summary [project]          Show project statistics');
                console.log('  backup [project]           Create manual backup');
                process.exit(1);
        }
    } catch (error) {
        console.error(`❌ Error: ${error.message}`);
        process.exit(1);
    }
}

module.exports = ClaudeTaskWarriorSync;