/**
 * Task Actions - Action implementations for individual task operations
 * Handles app installations, management operations, etc.
 */

class TaskActions {
  constructor(tasksManager, commands) {
    this.tasksManager = tasksManager;
    this.commands = commands;
  }

  /**
   * Install an application
   */
  async installApp(appName, config = '', resetNetwork = false) {
    try {
      this.commands.validateCommand('install', { appName });

      if (resetNetwork) {
        const parts = ['libreportal', 'app', 'install', appName];
        if (config) parts.push(`'${config.replace(/'/g, "'\\''")}'`);
        parts.push('--reset-network');
        return await this.executeTask('install', appName, parts.join(' '));
      }
      return await this.executeTask('install', appName, config);
    } catch (error) {
      throw new Error(`Failed to install ${appName}: ${error.message}`);
    }
  }

  /**
   * Uninstall an application
   */
  async uninstallApp(appName, deleteImage = false, deleteTasks = false) {
    try {
      this.commands.validateCommand('uninstall', { appName });
      // Build a verbatim command when the user opted into any flag so the
      // --delete-images / --delete-tasks switches survive executeTask's
      // standard command-builder (which would otherwise quote them as config args).
      const flags = [];
      if (deleteImage) flags.push('--delete-images');
      if (deleteTasks) flags.push('--delete-tasks');
      if (flags.length) {
        const command = `libreportal app uninstall ${appName} ${flags.join(' ')}`;
        return await this.executeTask('uninstall', appName, command);
      }
      return await this.executeTask('uninstall', appName);
    } catch (error) {
      throw new Error(`Failed to uninstall ${appName}: ${error.message}`);
    }
  }

  /**
   * Restart an application
   */
  async restartApp(appName) {
    try {
      this.commands.validateCommand('restart', { appName });
      return await this.executeTask('restart', appName);
    } catch (error) {
      throw new Error(`Failed to restart ${appName}: ${error.message}`);
    }
  }

  /**
   * Start an application
   */
  async startApp(appName) {
    try {
      this.commands.validateCommand('start', { appName });
      return await this.executeTask('start', appName);
    } catch (error) {
      throw new Error(`Failed to start ${appName}: ${error.message}`);
    }
  }

  /**
   * Stop an application
   */
  async stopApp(appName) {
    try {
      this.commands.validateCommand('stop', { appName });
      return await this.executeTask('stop', appName);
    } catch (error) {
      throw new Error(`Failed to stop ${appName}: ${error.message}`);
    }
  }

  /**
   * Create backup for an application
   */
  async backupApp(appName, customPassword = '') {
    try {
      this.commands.validateCommand('backup', { appName });
      return await this.executeTask('backup', appName, customPassword);
    } catch (error) {
      throw new Error(`Failed to backup ${appName}: ${error.message}`);
    }
  }

  async restoreApp(appName, location, backupFile, password) {
    try {
      if (!appName) throw new Error('appName is required');
      if (!backupFile) throw new Error('backupFile is required');

      const parts = ['libreportal', 'app', 'restore', appName];
      if (location) parts.push(location);
      parts.push(backupFile);
      if (password) parts.push(password);
      return await this.executeTask('restore', appName, parts.join(' '));
    } catch (error) {
      throw new Error(`Failed to restore ${appName}: ${error.message}`);
    }
  }

  /**
   * Delete backup file for an application
   */
  async deleteBackup(appName, backupFile, deleteRemote1 = 'false', deleteRemote2 = 'false') {
    try {
      // Build the command with all parameters
      const command = `libreportal backup app delete ${appName} ${backupFile} ${deleteRemote1} ${deleteRemote2}`;
      
      // Create task directly with the full command
      // createTask will handle monitoring
      const task = await this.tasksManager.taskManager.createTask(command, 'delete', appName, backupFile);
      
      // Emit taskCreated event for AppTabbedManager to track the task
      // This is needed for tab re-enabling on task completion
      window.dispatchEvent(new CustomEvent('taskCreated', {
        detail: { 
          taskId: task.id, 
          appName: appName, 
          action: 'delete',
          timestamp: Date.now()
        }
      }));
      
      return task;
    } catch (error) {
      throw new Error(`Failed to delete backup ${backupFile}: ${error.message}`);
    }
  }

  /**
   * Delete all backup files for an application
   */
  async deleteAllBackups(appName, deleteRemote1 = 'false', deleteRemote2 = 'false') {
    try {
      // Build the command with all parameters
      const command = `libreportal backup app delete_all ${appName} ${deleteRemote1} ${deleteRemote2}`;
      
      // Create task directly with the full command
      // createTask will handle monitoring
      const task = await this.tasksManager.taskManager.createTask(command, 'delete_all', appName, 'all');
      
      // Emit taskCreated event for AppTabbedManager to track the task
      // This is needed for tab re-enabling on task completion
      window.dispatchEvent(new CustomEvent('taskCreated', {
        detail: { 
          taskId: task.id, 
          appName: appName, 
          action: 'delete_all',
          timestamp: Date.now()
        }
      }));
      
      return task;
    } catch (error) {
      throw new Error(`Failed to delete all backups for ${appName}: ${error.message}`);
    }
  }

  /**
   * Update application configuration
   */
  async updateConfig(appName) {
    try {
      this.commands.validateCommand('update_config', { appName });

      await this.executeTask('update_config', appName);
      return;
    } catch (error) {
      throw new Error(`Failed to update config for ${appName}: ${error.message}`);
    }
  }

async configUpdate(changes) {
    try {
      if (!changes) throw new Error('No changes to save');
      const command = `libreportal config update ${changes}`;
      return await this.executeTask('config_update', 'system', command);
    } catch (error) {
      throw new Error(`Failed to update configuration: ${error.message}`);
    }
  }

  /**
   * Run a per-app tool from the Tools tab. Builds:
   *   libreportal app tool <appName> <toolName> '<argsString>'
   * argsString is pipe-encoded: key=value|key=value (matches the install
   * config pattern so the bash side can use the same parser).
   */
  async runTool(appName, toolName, toolArgs = '', toolLabel = '') {
    try {
      if (!appName) throw new Error('appName is required');
      if (!toolName) throw new Error('toolName is required');

      const safeTool = String(toolName).replace(/[^A-Za-z0-9_.-]/g, '');
      if (!safeTool) throw new Error('Invalid tool name');

      const parts = ['libreportal', 'app', 'tool', appName, safeTool];
      if (toolArgs) {
        parts.push(`'${String(toolArgs).replace(/'/g, "'\\''")}'`);
      }
      return await this.executeTask('tool', appName, parts.join(' '), toolLabel);
    } catch (error) {
      throw new Error(`Failed to run tool ${toolName} on ${appName}: ${error.message}`);
    }
  }

  /**
   * System operations
   */
  async systemUpdate() {
    try {
      await this.executeTask('system_update', 'system');
      return;
    } catch (error) {
      throw new Error(`Failed to update system: ${error.message}`);
    }
  }

  /**
   * Create a task object
   */
  createTask(type, command, metadata = {}) {
    const task = {
      id: Date.now().toString(),
      command: command,
      type: type,
      status: 'running',
      createdAt: new Date().toISOString(),
      output: `Starting ${type} operation...`,
      error: null,
      ...metadata
    };

    return task;
  }

  /**
   * Execute a task with enhanced event emission
   */
  async executeTask(action, appName, config = '', displayLabel = '') {
    try {
      // If config is a full `libreportal …` command, use it verbatim. Otherwise
      // build the standard form and single-quote the config arg.
      let command;
      if (config && config.startsWith('libreportal')) {
        command = config;
      } else {
        command = `libreportal app ${action} ${appName}`;
        if (config) command += ` '${config.replace(/'/g, "'\\''")}'`;
      }
      
      // Create task — POSTs to /api/tasks and returns the authoritative task.
      const task = await this.tasksManager.taskManager.createTask(command, action, appName, config);

      // Hook the UI side-effects (auto-expand, log streaming, status interval).
      // The bus also delivers `taskCreated` from the SSE feed; AppTabbedManager
      // dedupes by appName|action so the double-fire is harmless.
      if (this.tasksManager && typeof this.tasksManager.monitorTask === 'function') {
        this.tasksManager.monitorTask(task.id, appName, action);
      }

      window.dispatchEvent(new CustomEvent('taskCreated', {
        detail: {
          taskId: task.id,
          appName: appName,
          action: action,
          timestamp: Date.now()
        }
      }));
      
      // Show success notification
      let appData = null;
      try {
        appData = this.commands.getAppData ? this.commands.getAppData(appName) : null;
      } catch (error) {
        console.warn('Could not get app data:', error);
      }
      const appIcon = appData?.icon || `/icons/apps/${task.app}.svg`;
      
      let taskUrl;
      const currentUrl = window.location.href;
      
      if (currentUrl.includes('/app/') && appName) {
        taskUrl = `/app/${appName}?tab=tasks&task=${task.id}`;
      } else {
        taskUrl = `/tasks/all?task=${task.id}`;
      }
      
      if (window.notificationSystem) {
        const displayName = window.getAppDisplayName ? window.getAppDisplayName(appName) : appName;
        const typeIcon = (window.tasksManager && window.tasksManager.getTaskTypeIcon
          ? window.tasksManager.getTaskTypeIcon({ type: action })
          : null)?.icon || '';
        const customIcon = typeIcon ? `<span style="font-size:18px;line-height:1;">${typeIcon}</span>` : null;
        const headline = displayLabel
          ? `${displayLabel} task started!`
          : `${action.charAt(0).toUpperCase() + action.slice(1)} task started!`;
        window.notificationSystem.show(
          `<strong>App: ${displayName}</strong><br>${headline}`,
          'success',
          appName,
          taskUrl,
          appIcon,
          customIcon
        );
      }

      return task;
    } catch (error) {
      console.error(`❌ Failed to execute ${action} task for ${appName}:`, error);
      if (window.notificationSystem) {
        window.notificationSystem.error(`Failed to start ${action} task for ${appName}: ${error.message}`);
      }
      throw error;
    }
  }

  /**
   * Execute task monitoring (separated to avoid duplicate task creation)
   */
  async executeTaskMonitoring(task, appName, action) {
    // Emit task creation event for AppTabbedManager
    window.dispatchEvent(new CustomEvent('taskCreated', {
      detail: { 
        taskId: task.id, 
        appName: appName, 
        action: action,
        timestamp: Date.now()
      }
    }));
    
    // console.log(`✅ Task created: ${task.id} for ${action} on ${appName}`);
    
    // Set up monitoring for this specific task
    this.tasksManager.monitorTask(task.id, appName, action);
    
    // Try to get app data for better notifications
    let appData = null;
    try {
      appData = this.commands.getAppData ? this.commands.getAppData(appName) : null;
    } catch (error) {
      console.warn('Could not get app data:', error);
    }
    const appIcon = appData?.icon || `/icons/apps/${task.app}.svg`;
    
    // Smart URL generation - always include app name
    let taskUrl;
    const currentUrl = window.location.href;
    // console.log('🔍 TaskActions: Current URL:', currentUrl);
    
    // Always generate URL with app name for proper navigation
    if (currentUrl.includes('/app/') && appName) {
      // We're on an app page, maintain app context
      taskUrl = `/app/${appName}?tab=tasks&task=${task.id}`;
    } else {
      // We're on main tasks page, use normal URL
      taskUrl = `/tasks/all?task=${task.id}`;
    }
    
    // Show success notification with app icon and direct link
    if (window.notificationSystem) {
      const displayName = window.getAppDisplayName ? window.getAppDisplayName(appName) : appName;
      window.notificationSystem.show(
        `<strong>App: ${displayName}</strong><br>
        ${action.charAt(0).toUpperCase() + action.slice(1)} task started!`,
        'success',
        appName,
        taskUrl,
        appIcon
      );
    }
    
    return task;
  }
 
  /**
   * Update task in the manager
   */
  updateTaskInManager(updatedTask) {
    const taskIndex = this.tasksManager.tasks.findIndex(t => t.id === updatedTask.id);
    if (taskIndex !== -1) {
      this.tasksManager.tasks[taskIndex] = updatedTask;
      this.tasksManager.renderTasks();
      this.tasksManager.updateStats();
      this.tasksManager.updateSidebarCounts();
      this.tasksManager.generateAppCategories();
    }
  }
}

// Export for use
window.TaskActions = TaskActions;
