using System.Net; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; namespace CognitiveClarity.api { public class AnalysisRequest { [JsonPropertyName("turnContext")] public string TurnContext { get; set; } = string.Empty; [JsonPropertyName("scenarioTitle")] public string ScenarioTitle { get; set; } = string.Empty; [JsonPropertyName("scenarioDescription")] public string ScenarioDescription { get; set; } = string.Empty; [JsonPropertyName("cbtFocus")] public List CBTFocus { get; set; } = new(); [JsonPropertyName("model")] public string Model { get; set; } = "google/gemini-3.8-flash"; } public class AnalysisFunction { private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; public AnalysisFunction(ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory) { _logger = loggerFactory.CreateLogger(); _httpClientFactory = httpClientFactory; } [Function("ClinicalAnalysis")] public async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "analysis")] HttpRequestData req) { _logger.LogInformation("C# HTTP trigger function processed a clinical analysis request via OpenRouter."); var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var data = JsonSerializer.Deserialize(requestBody); if (data == null || string.IsNullOrWhiteSpace(data.TurnContext)) { var badResponse = req.CreateResponse(HttpStatusCode.BadRequest); await badResponse.WriteStringAsync("Please provide turnContext in the request body"); return badResponse; } var apiKey = System.Environment.GetEnvironmentVariable("OPENROUTER_API_KEY"); if (string.IsNullOrEmpty(apiKey)) { _logger.LogError("OPENROUTER_API_KEY is missing from environment variables."); return req.CreateResponse(HttpStatusCode.InternalServerError); } var systemAnalysisPrompt = $@"You are a master clinical psychologist specializing in Cognitive Behavioral Therapy (CBT). You are supervising an interactive CBT simulation. SCENARIO: {data.ScenarioTitle} - {data.ScenarioDescription} FOCUS AREAS: {string.Join(", ", data.CBTFocus)} Return ONLY a valid JSON object matching this schema: {{ ""analysis"": {{ ""distortions"": [""string""], ""isAdaptive"": boolean, ""evidence"": ""string"" }}, ""rating"": {{ ""score"": number (1-5), ""reason"": ""string"" }}, ""suggestions"": {{ ""alternativeThought"": ""string"", ""behavioralStep"": ""string"" }} }}"; var payload = new { model = string.IsNullOrEmpty(data.Model) ? "google/gemini-3.8-flash" : data.Model, messages = new object[] { new { role = "system", content = systemAnalysisPrompt }, new { role = "user", content = data.TurnContext } }, response_format = new { type = "json_object" }, temperature = 0.2 }; try { var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); client.DefaultRequestHeaders.Add("HTTP-Referer", "https://cognitive-clarity.app"); client.DefaultRequestHeaders.Add("X-Title", "Cognitive Clarity"); var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"); var response = await client.PostAsync("https://openrouter.ai/api/v1/chat/completions", content); if (!response.IsSuccessStatusCode) { var errText = await response.Content.ReadAsStringAsync(); _logger.LogError("OpenRouter returned error {Status}: {Error}", response.StatusCode, errText); var errResponse = req.CreateResponse(response.StatusCode); await errResponse.WriteStringAsync(errText); return errResponse; } var resJson = await response.Content.ReadAsStringAsync(); using var doc = JsonDocument.Parse(resJson); var rawResult = doc.RootElement .GetProperty("choices")[0] .GetProperty("message") .GetProperty("content") .GetString() ?? "{}"; var successResponse = req.CreateResponse(HttpStatusCode.OK); successResponse.Headers.Add("Content-Type", "application/json"); await successResponse.WriteStringAsync(rawResult); return successResponse; } catch (Exception ex) { _logger.LogError(ex, "Failed to generate analysis via OpenRouter API."); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteStringAsync("Error communicating with OpenRouter API."); return errorResponse; } } } }