unit MainUnit;

interface

uses
    Winapi.Windows,
    Winapi.Messages,
    System.SysUtils,
    System.Variants,
    System.Classes,
    Vcl.Graphics,
    Vcl.Controls,
    Vcl.Forms,
    Vcl.Dialogs,
    Vcl.StdCtrls,
    System.Net.HttpClient,
    System.Net.HttpClientComponent,
    System.JSON,
    System.Net.Mime,
    Vcl.AppEvnts,
    Myc.Futures,
    System.Generics.Collections,
    ApiKey;

type
    // NEU: Ein Record, um einen einzelnen Redebeitrag in der Konversation zu speichern
    TChatTurn = record
        Role: string; // 'user' oder 'model'
        Text: string;
    end;

    TForm1 = class(TForm)
        AnswerMemo: TMemo;
        ExecButton: TButton;
        ApplicationEvents: TApplicationEvents;
        PromptMemo: TMemo;
        procedure ExecButtonClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
    private
        FHttpClient: TNetHTTPClient;
        FMyApiKey: string;
        FAnswer: TFuture<String>;
        FChatHistory: TList<TChatTurn>; // NEU: Liste für den Konversationsverlauf
        procedure SendPrompt;
    public
    { Public declarations }
    end;

var
    Form1: TForm1;

implementation

{$R *.dfm}

const
    GEMINI_MODEL = 'gemini-2.5-flash-preview-05-20';
    API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models/';

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
    FHttpClient := TNetHTTPClient.Create(nil);
    FMyApiKey := ApiKey.Value; // Eingelesen aus ApiKey.pas

    // NEU: Initialisiert die Liste für den Konversationsverlauf
    FChatHistory := TList<TChatTurn>.Create;

    // Optional: Füge hier einen initialen System-Prompt hinzu, wenn gewünscht.
    // Dieser wird dann immer als erste Nachricht mitgesendet.
    // var initialTurn: TChatTurn;
    // initialTurn.Role := 'user';
    // initialTurn.Text := 'Du bist ein Delphi-Entwicklungs-Assistent...';
    // FChatHistory.Add(initialTurn);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
    FAnswer.WaitFor;
    FHttpClient.Free;
    FChatHistory.Free; // NEU: Gibt die Verlaufsliste frei
end;

procedure TForm1.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
var
    answerText: string;
    modelTurn: TChatTurn;
begin
    if FAnswer.Done.IsSet and not ExecButton.Enabled then
    begin
        answerText := FAnswer.Value;
        AnswerMemo.Lines.Add(answerText);

        // NEU: Füge die Antwort des Modells zum Verlauf hinzu
        if not answerText.StartsWith('Fehler!') then
        begin
            modelTurn.Role := 'model';
            modelTurn.Text := answerText;
            FChatHistory.Add(modelTurn);
        end;

        FAnswer := FAnswer.Null;
        ExecButton.Enabled := True;
    end;
end;

procedure TForm1.ExecButtonClick(Sender: TObject);
begin
    SendPrompt;
end;

procedure TForm1.SendPrompt;
var
    userPrompt: string;
    userTurn: TChatTurn;
begin
    if not ExecButton.Enabled then
        Exit;

    userPrompt := PromptMemo.Lines.Text;
    if userPrompt.IsEmpty then
    begin
        ShowMessage('Bitte geben Sie einen Prompt ein.');
        Exit;
    end;

    // NEU: Füge die aktuelle Benutzereingabe zum Verlauf hinzu
    userTurn.Role := 'user';
    userTurn.Text := userPrompt;
    FChatHistory.Add(userTurn);

    // NEU: Leere das Eingabefeld für die nächste Nachricht
    PromptMemo.Clear;

    ExecButton.Enabled := False;
    AnswerMemo.Lines.Add('');
    AnswerMemo.Lines.Add('--- [USER] ---');
    AnswerMemo.Lines.Add(userPrompt);
    AnswerMemo.Lines.Add('... sende Anfrage an Gemini ...');

    FAnswer :=
        TFuture<string>.Construct(
            function: string
            var
                jsonRequest: TJSONObject;
                jsonContents: TJSONArray;
                requestBody: TStringStream;
                response: IHTTPResponse;
                responseJson: TJSONValue;
                apiUrl: string;
                turn: TChatTurn;
            begin
                try
                    // 1. JSON-Body aus dem gesamten Konversationsverlauf erstellen
                    jsonRequest := TJSONObject.Create;
                    try
                        jsonContents := TJSONArray.Create;
                        jsonRequest.AddPair('contents', jsonContents);

                        // NEU: Iteriere durch den Verlauf und baue die JSON-Struktur auf
                        for turn in FChatHistory do
                        begin
                            var jsonTurn := TJSONObject.Create;
                            jsonTurn.AddPair('role', TJSONString.Create(turn.Role));

                            var jsonParts := TJSONArray.Create;
                            jsonTurn.AddPair('parts', jsonParts);

                            var jsonText := TJSONObject.Create;
                            jsonText.AddPair('text', TJSONString.Create(turn.Text));
                            jsonParts.Add(jsonText);

                            jsonContents.Add(jsonTurn);
                        end;

                        // 2. Request senden
                        requestBody := TStringStream.Create(jsonRequest.ToString, TEncoding.UTF8);
                        try
                            apiUrl := API_BASE_URL + GEMINI_MODEL + ':generateContent?key=' + FMyApiKey;
                            response := FHttpClient.Post(apiUrl, requestBody, nil);

                            // 3. Antwort verarbeiten
                            if (response.StatusCode = 200) then
                            begin
                                responseJson := TJSONObject.ParseJSONValue(response.ContentAsString(TEncoding.UTF8));
                                try
                                    Result :=
                                        responseJson
                                            .GetValue<TJSONArray>('candidates')
                                            .Items[0]
                                            .GetValue<TJSONObject>('content')
                                            .GetValue<TJSONArray>('parts')
                                            .Items[0]
                                            .GetValue<string>('text');
                                finally
                                    responseJson.Free;
                                end;
                            end
                            else
                            begin
                                Result :=
                                    'Fehler! Status: '
                                        + response.StatusCode.ToString
                                        + ' - '
                                        + response.StatusText
                                        + sLineBreak
                                        + response.ContentAsString;
                            end;
                        finally
                            requestBody.Free;
                        end;
                    finally
                        jsonRequest.Free;
                    end;
                except
                    on E: Exception do
                    begin
                        Result := '--- FEHLER IM TASK ---' + sLineBreak + E.Message;
                    end;
                end;
            end
        );
end;

end.
