"""Presentation service — generates HTML slides from idea + analysis reports."""
import json
import logging
from datetime import datetime, timezone
from typing import Any, Optional
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.models import AgentReport
from app.models.idea import Idea
from app.services.disk_service import DiskService
logger = logging.getLogger(__name__)
ROLE_EMOJI = {
"coordinator": "🎯",
"task_organizer": "📋",
"business_analyst": "💼",
"legal_expert": "⚖️",
"financial_consultant": "💰",
"solution_architect": "🏗️",
"tester": "🧪",
"ui_designer": "🎨",
"smm_specialist": "📱",
"life_coach": "🌟",
"accessibility_expert": "♿",
}
ROLE_LABELS = {
"coordinator": "Координатор",
"task_organizer": "Организатор задач",
"business_analyst": "Бизнес-аналитик",
"legal_expert": "Юрист",
"financial_consultant": "Финансовый консультант",
"solution_architect": "Архитектор решения",
"tester": "Тестировщик",
"ui_designer": "UI/Дизайнер",
"smm_specialist": "SMM-специалист",
"life_coach": "Лайф-коуч",
"accessibility_expert": "Эксперт доступности",
}
REVEAL_HTML_TEMPLATE = """
{title} — VoIdea Презентация
{title}
{author} · {status_label} · {date}
{executive_summary}
{role_slides}
Спасибо за внимание!
Создано в VoIdea · {date}
"""
class PresentationService:
def __init__(self, db: AsyncSession):
self.db = db
async def generate(
self,
idea_id: str,
roles: Optional[list[str]] = None,
user_name: str = "",
) -> Optional[str]:
"""Generate HTML presentation for an idea.
Args:
idea_id: UUID of the idea
roles: List of roles to include (None = all available)
user_name: Author display name
Returns:
HTML string or None if idea not found
"""
result = await self.db.execute(
select(Idea).where(Idea.id == idea_id)
)
idea = result.scalar_one_or_none()
if not idea:
return None
result = await self.db.execute(
select(AgentReport).where(
AgentReport.details["idea_id"].as_string() == idea_id
).order_by(AgentReport.created_at.asc())
)
reports = result.scalars().all()
if roles is not None:
reports = [
r for r in reports
if r.agent_id.replace("ai_", "") in roles
]
funnel_labels = {
"raw": "Сырая",
"validated": "Подтверждена",
"backlog": "Бэклог",
"in_progress": "В работе",
"launched": "Запущена",
"retrospective": "Ретроспектива",
}
status_label = funnel_labels.get(
idea.funnel_status or "", idea.funnel_status or "Без статуса"
)
date_str = datetime.now(timezone.utc).strftime("%d.%m.%Y")
role_slides = []
for r in reports:
role_name = r.agent_id.replace("ai_", "")
emoji = ROLE_EMOJI.get(role_name, "📄")
label = ROLE_LABELS.get(role_name, role_name)
content = r.message or "Нет данных"
role_slides.append(f"""
{emoji} {label}
{content}
""")
success_count = sum(1 for r in reports if r.success)
if role_slides:
exec_summary = f"""