package screens
import (
"context"
"fmt"
"strings"
"example.com/m/adapter/backend"
"example.com/m/bot"
"github.com/NicoNex/echotron/v3"
"github.com/rs/zerolog/log"
)
type PurchaseChannelInput struct {
Username string
PlannedCost *float64
Comment *string
}
type SelectChannelsForPurchase struct {
WorkspaceID string
ProjectID string
ProjectTitle string
CreativeID string
Channels []PurchaseChannelInput
BackState bot.State
}
func (s *SelectChannelsForPurchase) Enter(b *bot.Bot, mode bot.RenderMode) {
s.renderChannelSelection(b, mode)
}
func (s *SelectChannelsForPurchase) renderChannelSelection(b *bot.Bot, mode bot.RenderMode) {
text := "… › Создание › Каналы\n\n"
text += "Создание закупа\n\n"
text += "Шаг 2/2: Добавление каналов\n\n"
var buttons [][]echotron.InlineKeyboardButton
if len(s.Channels) == 0 {
text += `Добавьте каналы для размещения рекламы
Отправьте username канала (без @)
Например: channel_name
После добавления всех каналов нажмите Создать закуп`
} else {
text += fmt.Sprintf("Добавлено каналов: %d\n\n", len(s.Channels))
for i, ch := range s.Channels {
channelText := fmt.Sprintf(" %d. @%s", i+1, ch.Username)
if ch.PlannedCost != nil {
channelText += fmt.Sprintf(" — %.0f₽", *ch.PlannedCost)
}
text += channelText + "\n"
}
text += "\nДобавьте еще каналы или создайте закуп"
// Кнопка создания закупа (доступна только если есть каналы)
buttons = append(buttons, bot.Row(
bot.Button("● Создать закуп", "create"),
))
}
// Кнопки навигации
buttons = append(buttons, bot.Row(
bot.Button("← Назад", "back"),
))
keyboard := bot.Keyboard(buttons...)
b.Render(text, keyboard, mode)
}
func (s *SelectChannelsForPurchase) ensureJWT(b *bot.Bot) (string, error) {
if b.Session.JWT != "" {
return b.Session.JWT, nil
}
jwt, err := b.Backend.GetJWTByTelegramID(context.Background(), b.ChatID)
if err != nil {
return "", err
}
b.Session.JWT = jwt
return jwt, nil
}
func (s *SelectChannelsForPurchase) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
data := u.CallbackQuery.Data
switch data {
case "back":
// Возвращаемся к выбору креатива
b.SetState(&AddPurchase{
WorkspaceID: s.WorkspaceID,
ProjectID: s.ProjectID,
ProjectTitle: s.ProjectTitle,
BackState: s.BackState,
}, bot.EditMessage)
case "create":
if len(s.Channels) == 0 {
b.Edit("❌ Добавьте хотя бы один канал", bot.Keyboard(
bot.Row(bot.Button("← Назад", "back_to_select")),
))
return
}
jwt, err := s.ensureJWT(b)
if err != nil {
log.Error().Err(err).Msg("Failed to get JWT")
b.Edit("❌ Ошибка авторизации", bot.Keyboard())
return
}
// Создаем закуп
s.createPurchase(b, jwt)
case "back_to_select":
s.Enter(b, bot.EditMessage)
default:
s.Enter(b, bot.NewMessage)
}
}
func (s *SelectChannelsForPurchase) createPurchase(b *bot.Bot, jwt string) {
// Преобразуем каналы в формат API
var apiChannels []backend.CreatePurchaseChannelInput
for _, ch := range s.Channels {
apiChannels = append(apiChannels, backend.CreatePurchaseChannelInput{
Username: ch.Username,
PlannedCost: ch.PlannedCost,
Comment: ch.Comment,
})
}
input := backend.CreatePurchaseInput{
CreativeID: s.CreativeID,
Channels: apiChannels,
}
purchase, err := b.Backend.CreatePurchase(
context.Background(),
jwt,
s.WorkspaceID,
s.ProjectID,
input,
)
if err != nil {
log.Error().Err(err).Msg("Failed to create purchase")
b.Edit("❌ Не удалось создать закуп\n\nВозможные причины:\n• Один из каналов не найден\n• Ошибка сервера", bot.Keyboard(
bot.Row(bot.Button("← Назад", "back_to_select")),
))
return
}
// Показываем успешное создание
successText := fmt.Sprintf(`… › Создание › Готово
Закуп создан
▪ ID: %s
▪ Креатив: %s
▪ Каналов: %d
Закуп создан и готов к работе`, purchase.ID, purchase.CreativeID, len(purchase.Channels))
b.Edit(successText, bot.Keyboard(
bot.Row(bot.Button("● Готово", "done")),
))
}
func (s *SelectChannelsForPurchase) HandleMessage(b *bot.Bot, u *echotron.Update) {
if u.Message == nil || u.Message.Text == "" {
return
}
username := strings.TrimSpace(u.Message.Text)
// Убираем @ если пользователь его добавил
username = strings.TrimPrefix(username, "@")
if username == "" {
return
}
// Проверяем, не добавлен ли уже этот канал
for _, ch := range s.Channels {
if ch.Username == username {
b.SendNew(fmt.Sprintf("⚠️ Канал @%s уже добавлен в список", username), bot.Keyboard())
return
}
}
// Добавляем канал в список
s.Channels = append(s.Channels, PurchaseChannelInput{
Username: username,
})
// Обновляем экран
s.Enter(b, bot.NewMessage)
}
func (s *SelectChannelsForPurchase) Handle(b *bot.Bot, u *echotron.Update) {
// Обрабатываем callback после успешного создания
if u.CallbackQuery != nil && u.CallbackQuery.Data == "done" {
// Возвращаемся к списку закупов
if s.BackState != nil {
b.SetState(s.BackState, bot.EditMessage)
}
}
}