using System.Globalization;
using System.Text;
namespace GerbilManagerWebAPI.SaleAd
{
///
/// FEAT-12a: assembles the German prompt for the sale-ad (Abgabe-Inserat)
/// generation. Style and rules follow the breeder's real Jimdo listings
/// (analysed in hive/agents/god/FEAT12-jimdo-publish-research.md):
/// group-based listings, status line, bold emotive tagline, per-animal
/// Farbschlag + "geboren am DD.MM.YYYY" + personality prose, NO PRICES.
///
public static class SaleAdPromptBuilder
{
///
/// Two few-shot examples derived from the documented listing template.
/// NOTE: the research file documents the format and one real tagline;
/// these examples are synthesized to that template. Swap in verbatim
/// listings from kleine-chaoten.jimdofree.com when available.
///
private const string ExampleListing1 = """
Status: FREI
„Großer und kleiner Bruder Dynamik“ – Männliches Rennmaus-Duo sucht ein liebevolles Zuhause
Balu – CP-Agouti, geboren am 12.03.2024
Balu ist der ruhige Pol des Duos: Er beobachtet erst in aller Seelenruhe und buddelt sich dann zielstrebig durch jedes Einstreu-Projekt. Aus der Hand nimmt er Leckerlis schon ganz vorsichtig.
Benny – Schwarz Schecke, geboren am 12.03.2024
Benny ist der Entdecker: kein Röhrchen bleibt unerforscht, kein Häuschen unbewohnt. Mit seinem Bruder kuschelt er sich abends ins Nest — getrennt werden die beiden deshalb nicht.
Die zwei werden nur gemeinsam in ein rennmausgerechtes Zuhause abgegeben.
""";
private const string ExampleListing2 = """
Status: LOCKER RESERVIERT Anna
„Zwei Schwestern, ein Herz und ganz viel Neugier“ – Weibliches Duo sucht seine Menschen
Frieda – Gold, geboren am 28.06.2024
Frieda ist die Mutige der beiden und steht beim Öffnen des Geheges sofort am Glas. Sie liebt Kolbenhirse und nimmt sie dir behutsam aus den Fingern.
Fine – Agouti, geboren am 28.06.2024
Fine ist etwas zurückhaltender, taut aber neben ihrer Schwester schnell auf. Beim abendlichen Buddeln sind die zwei ein unschlagbares Team.
Die Schwestern ziehen selbstverständlich nur zusammen um.
""";
/// System prompt: role, style description, hard rules, few-shot examples.
public static string BuildSystemPrompt() => $"""
Du schreibst Abgabe-Inserate für Mongolische Rennmäuse im Stil der „Zucht der kleinen Chaoten“.
Stil und Aufbau (verbindlich):
- Erste Zeile: die Status-Zeile, exakt wie vorgegeben (z. B. „Status: FREI“).
- Danach eine fette, emotionale Überschrift (Tagline) in Anführungszeichen mit kurzem Untertitel, die den Charakter der Gruppe einfängt.
- Danach pro Tier ein Absatz: Name – Farbschlag, geboren am TT.MM.JJJJ, gefolgt von warmherziger Persönlichkeits-Prosa auf Basis der mitgelieferten Notizen.
- Abschluss: ein Satz, dass die Tiere nur gemeinsam in ein artgerechtes Zuhause abgegeben werden.
Harte Regeln:
- NIEMALS Preise oder Schutzgebühren nennen.
- KEINE Fakten erfinden: Verwende ausschließlich die mitgelieferten Daten (Namen, Farbschläge, Geburtsdaten, Notizen). Fehlt eine Angabe, lässt du sie weg.
- Sprache: Deutsch, warm und liebevoll, aber nicht kitschig-übertrieben.
- Gib NUR den Inserat-Text aus — keine Erklärungen, keine Markdown-Code-Blöcke.
Beispiel 1:
{ExampleListing1}
Beispiel 2:
{ExampleListing2}
""";
/// User prompt: the actual group data + the user's free-text hints.
public static string BuildUserPrompt(SaleAdRequest request)
{
var sb = new StringBuilder();
sb.AppendLine("Erstelle ein Abgabe-Inserat für folgende Gruppe:");
sb.AppendLine();
sb.AppendLine($"Status-Zeile: {request.StatusLine}");
sb.AppendLine();
sb.AppendLine("Tiere:");
foreach (var animal in request.Animals)
{
sb.Append($"- Name: {animal.Name}");
if (!string.IsNullOrWhiteSpace(animal.Farbschlag))
sb.Append($" | Farbschlag: {animal.Farbschlag}");
if (!string.IsNullOrWhiteSpace(animal.DateOfBirth))
sb.Append($" | geboren am {FormatGermanDate(animal.DateOfBirth)}");
if (!string.IsNullOrWhiteSpace(animal.Notes))
sb.Append($" | Notizen: {animal.Notes}");
if (animal.Traits is { Count: > 0 })
sb.Append($" | Charakter: {string.Join(", ", animal.Traits)}");
if (!string.IsNullOrWhiteSpace(animal.CharacterNote))
sb.Append($" | Charakter-Notiz: {animal.CharacterNote}");
sb.AppendLine();
}
if (!string.IsNullOrWhiteSpace(request.Hints))
{
sb.AppendLine();
sb.AppendLine($"Wünsche/Hinweise: {request.Hints}");
}
return sb.ToString();
}
/// ISO "YYYY-MM-DD" -> "TT.MM.JJJJ"; anything else passes through verbatim.
internal static string FormatGermanDate(string isoDate) =>
DateOnly.TryParseExact(isoDate, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.None, out var date)
? date.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture)
: isoDate;
}
}