package telegram import ( "sync" "github.com/google/uuid" ) // Состояния пользователя type State int const ( StateNone State = iota StateAddServerURL StateAddServerLogin StateAddServerPassword StateAddServerConfirmName StateAddServerInputName StateBillingGiftURL // Состояния редактора черновиков (начиная с 100) StateDraftEditItemName State = 100 // Ожидание ввода нового названия позиции StateDraftEditItemQty State = 101 // Ожидание ввода количества StateDraftEditItemPrice State = 102 // Ожидание ввода цены ) // UserContext хранит временные данные в процессе диалога type UserContext struct { State State // Поля для добавления сервера TempURL string TempLogin string TempPassword string TempServerName string // Поля для биллинга BillingTargetURL string // Поля редактора черновиков EditingDraftID uuid.UUID // ID редактируемого черновика EditingItemID uuid.UUID // ID редактируемой позиции (DraftInvoiceItem) EditingItemIndex int // Порядковый номер позиции (1-based, для отображения пользователю) DraftMenuMsgID int // ID сообщения со списком позиций (для обновления через EditMessage) DraftCurrentPage int // Текущая страница пагинации (0-based) } // StateManager управляет состояниями type StateManager struct { mu sync.RWMutex states map[int64]*UserContext } func NewStateManager() *StateManager { return &StateManager{ states: make(map[int64]*UserContext), } } func (sm *StateManager) GetState(userID int64) State { sm.mu.RLock() defer sm.mu.RUnlock() if ctx, ok := sm.states[userID]; ok { return ctx.State } return StateNone } func (sm *StateManager) SetState(userID int64, state State) { sm.mu.Lock() defer sm.mu.Unlock() if _, ok := sm.states[userID]; !ok { sm.states[userID] = &UserContext{} } sm.states[userID].State = state } func (sm *StateManager) GetContext(userID int64) *UserContext { sm.mu.RLock() defer sm.mu.RUnlock() if ctx, ok := sm.states[userID]; ok { return ctx } return &UserContext{} // Return empty safe struct } func (sm *StateManager) UpdateContext(userID int64, updater func(*UserContext)) { sm.mu.Lock() defer sm.mu.Unlock() if _, ok := sm.states[userID]; !ok { sm.states[userID] = &UserContext{} } updater(sm.states[userID]) } func (sm *StateManager) Reset(userID int64) { sm.mu.Lock() defer sm.mu.Unlock() delete(sm.states, userID) } // ResetDraftEditor сбрасывает только поля редактора черновика func (sm *StateManager) ResetDraftEditor(userID int64) { sm.mu.Lock() defer sm.mu.Unlock() if ctx, ok := sm.states[userID]; ok { ctx.State = StateNone ctx.EditingDraftID = uuid.Nil ctx.EditingItemID = uuid.Nil ctx.EditingItemIndex = 0 ctx.DraftMenuMsgID = 0 ctx.DraftCurrentPage = 0 } } // InitDraftEditor инициализирует FSM для редактора черновика func (sm *StateManager) InitDraftEditor(userID int64, draftID uuid.UUID) { sm.mu.Lock() defer sm.mu.Unlock() if _, ok := sm.states[userID]; !ok { sm.states[userID] = &UserContext{} } ctx := sm.states[userID] ctx.State = StateNone ctx.EditingDraftID = draftID ctx.EditingItemID = uuid.Nil ctx.EditingItemIndex = 0 ctx.DraftMenuMsgID = 0 ctx.DraftCurrentPage = 0 }