using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace MarketAlly.AIPlugin.ClaudeCode.Controllers; /// /// API controller providing Claude Code integration endpoints /// [ApiController] [Route("api/[controller]")] [Produces("application/json")] public class ClaudeCodeLearningController : ControllerBase { private readonly IClaudeCodeService _claudeCodeService; private readonly IChatService _chatService; private readonly IContextClaudeService _contextService; private readonly ILogger _logger; public ClaudeCodeLearningController( IClaudeCodeService claudeCodeService, IChatService chatService, IContextClaudeService contextService, ILogger logger) { _claudeCodeService = claudeCodeService; _chatService = chatService; _contextService = contextService; _logger = logger; } /// /// Send a chat message to Claude Code /// /// Chat request /// Cancellation token /// Claude's response [HttpPost("chat")] public async Task SendChatMessage([FromBody] ChatRequest request, CancellationToken cancellationToken = default) { try { var response = await _claudeCodeService.SendChatMessageAsync(request, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in SendChatMessage"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Analyze code or a file /// /// Analysis request /// Cancellation token /// Analysis results [HttpPost("analyze")] public async Task AnalyzeCode([FromBody] AnalysisRequest request, CancellationToken cancellationToken = default) { try { var response = await _claudeCodeService.AnalyzeCodeAsync(request, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in AnalyzeCode"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Get current rate limit status /// /// Cancellation token /// Rate limit information [HttpGet("rate-limit/status")] public async Task GetRateLimitStatus(CancellationToken cancellationToken = default) { try { var response = await _claudeCodeService.GetRateLimitStatusAsync(cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode }); } catch (Exception ex) { _logger.LogError(ex, "Error in GetRateLimitStatus"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Search project context /// /// Search query /// Optional project path /// Cancellation token /// Search results [HttpGet("context/search")] public async Task SearchContext( [FromQuery] string query, [FromQuery] string? projectPath = null, CancellationToken cancellationToken = default) { try { if (string.IsNullOrWhiteSpace(query)) { return BadRequest(new { success = false, error = "Query parameter is required" }); } var response = await _claudeCodeService.SearchContextAsync(query, projectPath, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in SearchContext"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Store a decision or insight /// /// Decision storage request /// Cancellation token /// Success response [HttpPost("context/store-decision")] public async Task StoreDecision([FromBody] StoreDecisionRequest request, CancellationToken cancellationToken = default) { try { var response = await _claudeCodeService.StoreDecisionAsync(request, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in StoreDecision"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Start a new chat session /// /// Session start request /// Cancellation token /// New session information [HttpPost("sessions/start")] public async Task StartSession([FromBody] StartSessionRequest request, CancellationToken cancellationToken = default) { try { var response = await _chatService.StartSessionAsync(request, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in StartSession"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Get active chat sessions /// /// Cancellation token /// List of active sessions [HttpGet("sessions")] public async Task GetActiveSessions(CancellationToken cancellationToken = default) { try { var response = await _chatService.GetActiveSessionsAsync(cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in GetActiveSessions"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// Get session history /// /// Session identifier /// Maximum messages to return /// Cancellation token /// Session message history [HttpGet("sessions/{sessionId}/history")] public async Task GetSessionHistory( string sessionId, [FromQuery] int maxMessages = 50, CancellationToken cancellationToken = default) { try { var response = await _chatService.GetSessionHistoryAsync(sessionId, maxMessages, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in GetSessionHistory"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } /// /// End a chat session /// /// Session identifier /// Cancellation token /// Success response [HttpPost("sessions/{sessionId}/end")] public async Task EndSession(string sessionId, CancellationToken cancellationToken = default) { try { var response = await _chatService.EndSessionAsync(sessionId, cancellationToken); if (response.Success) { return Ok(new { success = true, data = response.Data, rateLimitInfo = response.RateLimitInfo }); } return BadRequest(new { success = false, error = response.Error, errorCode = response.ErrorCode, rateLimitInfo = response.RateLimitInfo }); } catch (Exception ex) { _logger.LogError(ex, "Error in EndSession"); return StatusCode(500, new { success = false, error = "Internal server error" }); } } }