Привет! Я хочу провести глубокий рефакторинг метода generateJsonAnalysis в классе MarketingAnalysisService.java.

У нас нет ограничений по токенам, но есть жесткое требование к качеству и детализации данных. Текущий метод пытается получить всё за один запрос, из-за чего страдает глубина.

ЗАДАЧА:
Перепиши метод generateJsonAnalysis так, чтобы он выполнял агрегацию данных из нескольких отдельных запросов к OpenAI.
Метод должен вызывать приватные helper-методы (создай их), каждый из которых отвечает за свою часть и возвращает Map<String, Object>.

СТРУКТУРА НОВОГО МЕТОДА:

1. Вызвать getAudienceAnalysis(request) -> возвращает секцию "audienceAnalysis"
2. Вызвать getCompetitorAnalysis(request) -> возвращает секцию "competitorAnalysis"
3. Вызвать getSeasonalityAndMarket(request) -> возвращает секцию "seasonality" и "market"
4. Объединить результаты в один Map<String, Object> и вернуть его.

ДЕТАЛИЗАЦИЯ HELPER-МЕТОДОВ (Промпты внутри них):

--- Метод 1: getAudienceAnalysis ---
Промпт должен требовать JSON строго такой структуры (для отрисовки виджетов на фронте):
{
"audienceAnalysis": {
"ageGroups": { "18-24": 15, "25-34": 40, "35-44": 30, "45+": 15 }, // Pie chart data
"ageComment": "Текст вывода под графиком возраста (1-2 предложения)",
"genderDistribution": { "Женщины": 60, "Мужчины": 40 }, // Donut chart
"genderComment": "Текст вывода под графиком пола",
"segments": [ // Список из 4 детальных карточек сегментов
{
"name": "Название (например 'Молодые профессионалы')",
"sharePercent": 35,
"ageRange": "25-34",
"incomeLevel": "Средний+",
"motivation": "Ключевая мотивация покупки",
"triggers": "Триггеры (на что реагируют)",
"primaryChannels": ["Instagram", "TikTok"], // Топ каналы для этого сегмента
"secondaryChannels": ["Telegram"]
}
],
"segmentsChannelMatrix": [ // Для таблицы heatmap: Сегмент vs Канал
{ "segmentName": "Молодые профи", "instagram": "high", "telegram": "medium", "youtube": "low" }
],
"keyTakeaways": ["Вывод 1", "Вывод 2", "Вывод 3"]
}
}

--- Метод 2: getCompetitorAnalysis ---
Промпт должен требовать JSON:
{
"competitorAnalysis": {
"marketShareChart": [ // Оценочные доли рынка для графика
{ "name": "Наш бренд", "value": 25 },
{ "name": "Конкурент А", "value": 30 },
{ "name": "Конкурент B", "value": 20 },
{ "name": "Другие", "value": 25 }
],
"marketShareComment": "Вывод по доле рынка",
"competitorsDetails": [ // Детали по 3-4 конкурентам
{
"name": "Конкурент А",
"priceStrategy": "Высокая/Средняя/Низкая",
"digitalMetrics": { "reach": 50000, "followers": 12000, "activityIndex": 85 },
"channelsHeatmap": { // Оценка (0-100) качества ведения канала
"Instagram": 90, "TikTok": 20, "Telegram": 70, "YouTube": 40
}
}
],
"comparisonTable": [ // Сравнительная таблица (5-6 характеристик)
{ "feature": "Ценовая политика", "us": "Средняя", "compA": "Высокая", "compB": "Низкая" },
{ "feature": "УТП", "us": "Сервис", "compA": "Бренд", "compB": "Дешевизна" }
],
"swotCompetitors": { // Краткий SWOT по рынку в целом
"strengths": ["..."], "weaknesses": ["..."]
},
"keyInsights": ["Вывод 1", "Вывод 2"]
}
}

ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ:

1. Используй существующий `openAIAnalyticsService.generateWithInstruction` для вызовов.
2. В каждом helper-методе добавь отдельный `try-catch` и логирование, чтобы падение одной части не ломало весь отчет (возвращай пустую Map или stub-данные при ошибке).
3. Используй `objectMapper` для парсинга ответов.
4. Убедись, что JSON очищается от markdown-тегов (```json) перед парсингом.

Пожалуйста, полностью реализуй этот модульный подход.
