// Copyright (c) Microsoft. All rights reserved.

// This sample shows how to download files generated by Code Interpreter using Microsoft Foundry.
// Code Interpreter generates files inside containers (cfile_ / cntr_ IDs) which cannot be
// downloaded via the standard Files API. Use ContainerClient from the project's OpenAI client instead.

#pragma warning disable OPENAI001

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI.Responses;

string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-4o-mini";

// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());

// Create an agent with Code Interpreter tool enabled
AIAgent agent = aiProjectClient.AsAIAgent(
    deploymentName,
    instructions: "You are a helpful assistant that can generate files using code.",
    name: "CodeInterpreterAgent",
    tools: [new HostedCodeInterpreterTool()]);

// Ask the agent to generate a file
AgentResponse response = await agent.RunAsync(
    "Create a CSV file with the multiplication times tables from 1 to 12. Include headers.");

// Display the text response
foreach (TextContent textContent in response.Messages.SelectMany(x => x.Contents).OfType<TextContent>())
{
    Console.WriteLine(textContent.Text);
}

// Extract container file citations from response annotations and download.
// AIProjectClient.GetProjectOpenAIClient() returns a ProjectOpenAIClient (inherits from OpenAI.OpenAIClient)
// which supports GetContainerClient(), unlike AzureOpenAIClient which does not.
var containerClient = aiProjectClient.GetProjectOpenAIClient().GetContainerClient();

HashSet<string> downloadedFiles = [];
bool foundContainerFiles = false;

foreach (AIContent content in response.Messages.SelectMany(x => x.Contents))
{
    if (content.Annotations is null)
    {
        continue;
    }

    foreach (AIAnnotation annotation in content.Annotations)
    {
        // Container files from Code Interpreter have ContainerFileCitationMessageAnnotation as raw representation
        if (annotation is CitationAnnotation citation
            && citation.RawRepresentation is ContainerFileCitationMessageAnnotation containerCitation)
        {
            foundContainerFiles = true;

            // Deduplicate by container+file ID in case the same file is cited multiple times
            string key = $"{containerCitation.ContainerId}/{containerCitation.FileId}";
            if (!downloadedFiles.Add(key))
            {
                continue;
            }

            Console.WriteLine($"\nDownloading container file: {containerCitation.Filename}");
            Console.WriteLine($"  Container ID: {containerCitation.ContainerId}");
            Console.WriteLine($"  File ID:      {containerCitation.FileId}");

            BinaryData fileData = await containerClient.DownloadContainerFileAsync(
                containerCitation.ContainerId,
                containerCitation.FileId);

            // Sanitize filename to prevent path traversal
            string safeFilename = Path.GetFileName(containerCitation.Filename);
            string outputPath = Path.Combine(Directory.GetCurrentDirectory(), safeFilename);
            await File.WriteAllBytesAsync(outputPath, fileData.ToArray());
            Console.WriteLine($"  Saved to:     {outputPath}");
        }
    }
}

if (!foundContainerFiles)
{
    Console.WriteLine("\nNo container file citations found in the response.");
    Console.WriteLine("The model may not have generated a downloadable file for this prompt.");
}
