package toc

import (
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"tgchanbot/internal/storage"

	tele "gopkg.in/telebot.v3"
)

const (
	captionCharLimit = 950  // photo caption 字符上限（预留安全余量）
	textCharLimit    = 3900 // 纯文本消息字符上限

	// CbPrefixTocPage 翻页回调前缀，导出供 telegram 包使用
	CbPrefixTocPage = "tocpage:"
)

type Manager struct {
	storage    *storage.Storage
	bot        *tele.Bot
	chanID     int64
	debounce   time.Duration
	coverImage string

	mu      sync.Mutex
	pending bool
	timer   *time.Timer
	stopCh  chan struct{}
}

func NewManager(store *storage.Storage, bot *tele.Bot, chanID int64, debounce time.Duration, coverImage string) *Manager {
	return &Manager{
		storage:    store,
		bot:        bot,
		chanID:     chanID,
		debounce:   debounce,
		coverImage: coverImage,
		stopCh:     make(chan struct{}),
	}
}

func (m *Manager) TriggerUpdate() {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.pending = true

	if m.timer != nil {
		m.timer.Stop()
	}

	m.timer = time.AfterFunc(m.debounce, func() {
		m.doUpdate()
	})
}

func (m *Manager) doUpdate() {
	m.mu.Lock()
	m.pending = false
	m.mu.Unlock()

	if err := m.DoUpdatePage(1); err != nil {
		log.Printf("TOC update error: %v", err)
	}
}

// DoUpdatePage 渲染指定页并更新频道 TOC 消息
func (m *Manager) DoUpdatePage(page int) error {
	charLimit := captionCharLimit
	if m.coverImage == "" {
		charLimit = textCharLimit
	}

	content, totalPages, err := m.RenderPage(page, charLimit)
	if err != nil {
		return fmt.Errorf("TOC render error: %w", err)
	}

	var markup *tele.ReplyMarkup
	if totalPages > 1 {
		markup = m.buildPageKeyboard(page, totalPages)
	}

	return m.updateMessage(content, markup)
}

// HandlePageCallback 处理翻页回调，供 telegram 包调用
func (m *Manager) HandlePageCallback(page int) error {
	return m.DoUpdatePage(page)
}

// buildPageKeyboard 构建翻页 inline keyboard
func (m *Manager) buildPageKeyboard(currentPage, totalPages int) *tele.ReplyMarkup {
	menu := &tele.ReplyMarkup{}
	var btns []tele.Btn

	// 回到第一页（非首页时显示）
	if currentPage > 1 {
		btns = append(btns, menu.Data("⏮", CbPrefixTocPage+"1"))
	}

	// 上一页（非首页时显示）
	if currentPage > 1 {
		btns = append(btns, menu.Data("⬅️", fmt.Sprintf("%s%d", CbPrefixTocPage, currentPage-1)))
	}

	// 下一页（非末页时显示）
	if currentPage < totalPages {
		btns = append(btns, menu.Data("➡️", fmt.Sprintf("%s%d", CbPrefixTocPage, currentPage+1)))
	}

	if len(btns) > 0 {
		menu.Inline(menu.Row(btns...))
	}

	return menu
}

func (m *Manager) updateMessage(content string, markup *tele.ReplyMarkup) error {
	chat := &tele.Chat{ID: m.chanID}

	msgID, err := m.storage.GetTocMsgID()
	if err != nil {
		return err
	}

	// 带封面图片模式
	if m.coverImage != "" {
		return m.updateWithPhoto(chat, msgID, content, markup)
	}

	// 纯文本模式
	if msgID == 0 {
		return m.sendNewText(chat, content, markup)
	}

	existingMsg := &tele.Message{
		ID:   msgID,
		Chat: chat,
	}

	opts := []interface{}{tele.ModeHTML, tele.NoPreview}
	if markup != nil {
		opts = append(opts, markup)
	}

	_, err = m.bot.Edit(existingMsg, content, opts...)
	if err != nil {
		errMsg := err.Error()
		if err == tele.ErrMessageNotModified || strings.Contains(errMsg, "message is not modified") {
			return nil
		}
		if strings.Contains(errMsg, "message to edit not found") {
			return m.sendNewText(chat, content, markup)
		}
		return err
	}

	return nil
}

func (m *Manager) sendNewText(chat *tele.Chat, content string, markup *tele.ReplyMarkup) error {
	opts := []interface{}{tele.ModeHTML, tele.NoPreview}
	if markup != nil {
		opts = append(opts, markup)
	}

	msg, err := m.bot.Send(chat, content, opts...)
	if err != nil {
		return err
	}
	return m.storage.SetTocMsgID(msg.ID)
}

func (m *Manager) updateWithPhoto(chat *tele.Chat, msgID int, content string, markup *tele.ReplyMarkup) error {
	photo := &tele.Photo{
		File:    tele.FromDisk(m.coverImage),
		Caption: content,
	}

	if msgID == 0 {
		opts := []interface{}{tele.ModeHTML}
		if markup != nil {
			opts = append(opts, markup)
		}
		msg, err := m.bot.Send(chat, photo, opts...)
		if err != nil {
			return err
		}
		return m.storage.SetTocMsgID(msg.ID)
	}

	existingMsg := &tele.Message{
		ID:   msgID,
		Chat: chat,
	}

	// 编辑图片消息的 caption
	opts := []interface{}{tele.ModeHTML}
	if markup != nil {
		opts = append(opts, markup)
	}

	_, err := m.bot.EditCaption(existingMsg, content, opts...)
	if err != nil {
		errMsg := err.Error()
		if err == tele.ErrMessageNotModified || strings.Contains(errMsg, "message is not modified") {
			return nil
		}
		if strings.Contains(errMsg, "message to edit not found") ||
			strings.Contains(errMsg, "no caption") {
			opts := []interface{}{tele.ModeHTML}
			if markup != nil {
				opts = append(opts, markup)
			}
			msg, err := m.bot.Send(chat, photo, opts...)
			if err != nil {
				return err
			}
			return m.storage.SetTocMsgID(msg.ID)
		}
		return err
	}

	return nil
}

func (m *Manager) Stop() {
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.timer != nil {
		m.timer.Stop()
	}

	close(m.stopCh)
}
