package telegram

import (
	"fmt"
	"regexp"
	"strings"
	"sync"
	"time"

	"tgchanbot/internal/storage"

	tele "gopkg.in/telebot.v3"
)

const (
	cbPrefixCat     = "cat:"
	cbPrefixConfirm = "confirm:"
	cbPrefixTitle   = "title:"
	cbCancel        = "cancel"

	albumCollectDelay = 500 * time.Millisecond // 等待相册其他消息的时间
)

// 相册收集定时器
var (
	albumTimers   = make(map[int64]*time.Timer)
	albumTimersMu sync.Mutex
)

var directURLPattern = regexp.MustCompile(`https?://[^\s<>"']+`)

func (b *Bot) handlePost(c tele.Context) error {
	msg := c.Message()
	payload := strings.TrimSpace(c.Message().Payload)

	// 快捷方式: 回复消息 + /post <分类> /tt <标题>
	if msg.ReplyTo != nil && payload != "" {
		return b.handleQuickPost(c, msg.ReplyTo, payload)
	}

	// 常规交互流程
	b.states.StartPost(c.Sender().ID)
	return c.Reply("📨 请转发需要归档到目录的消息\n\n消息将被同步发送到频道并添加到目录\n\n💡 快捷方式: 回复消息并发送\n`/post <分类> /tt <标题>`", tele.ModeMarkdown)
}

func (b *Bot) handleQuickPost(c tele.Context, replyMsg *tele.Message, payload string) error {
	// 解析: <分类> /tt <标题>
	parts := strings.SplitN(payload, "/tt", 2)
	category := strings.TrimSpace(parts[0])

	var title string
	if len(parts) > 1 {
		title = strings.TrimSpace(parts[1])
	}

	if category == "" {
		return c.Reply("❌ 用法: /post <分类> /tt <标题>\n例如: /post iOS /tt 某个APP推荐")
	}

	// 验证分类存在
	if !b.storage.CategoryExists(category) {
		categories, _ := b.storage.ListCategories()
		var names []string
		for _, cat := range categories {
			names = append(names, cat.Name)
		}
		return c.Reply(fmt.Sprintf("❌ 分类 [%s] 不存在\n\n可用分类: %s", category, strings.Join(names, ", ")))
	}

	// 标题: 优先使用指定标题，否则从回复消息提取
	if title == "" {
		title = extractTitle(replyMsg)
	}

	channelLink := buildMessageLinkFromReply(c.Message(), replyMsg)
	directLink := extractDirectLink(replyMsg)

	// 创建条目
	entry, err := b.storage.CreateEntry(category, title, channelLink, directLink)
	if err != nil {
		return c.Reply(fmt.Sprintf("❌ 保存失败: %v", err))
	}

	b.toc.TriggerUpdate()

	return c.Reply(fmt.Sprintf("✅ 已添加\n\nID: `%s`\n分类: %s\n标题: %s\n链接: %s",
		entry.ID, entry.Category, entry.Title, entry.MessageLink()), tele.ModeMarkdown)
}

func buildMessageLinkFromReply(currentMsg, replyMsg *tele.Message) string {
	chat := currentMsg.Chat
	msgID := replyMsg.ID

	if chat.Username != "" {
		return fmt.Sprintf("https://t.me/%s/%d", chat.Username, msgID)
	}

	chatID := chat.ID
	if chatID < 0 {
		chatID = -chatID - 1000000000000
	}
	return fmt.Sprintf("https://t.me/c/%d/%d", chatID, msgID)
}

func (b *Bot) handleTextInput(c tele.Context) error {
	msg := c.Message()
	if msg == nil {
		return nil
	}

	// 只处理私聊消息，忽略群组对话
	if c.Chat().Type != tele.ChatPrivate {
		return nil
	}

	// 检查是否为转发消息（OriginalUnixtime 在隐私设置隐藏来源时仍存在）
	isForwarded := msg.OriginalChat != nil || msg.OriginalSender != nil || msg.OriginalUnixtime > 0

	state := b.states.Get(c.Sender().ID)

	// 私聊收到转发消息，直接启动投稿流程（无需先 /post）
	if isForwarded && b.isAdmin(c.Sender().ID) {
		if state == nil {
			b.states.StartPost(c.Sender().ID)
		}
		if state == nil || state.Step == StepAwaitForward {
			return b.handleForwarded(c)
		}
	}

	if state == nil {
		return nil
	}

	// 自定义标题输入 (StepAwaitTitle)
	if state.Step == StepAwaitTitle {
		return b.handleTitleInput(c)
	}

	return nil
}

func (b *Bot) handleForwarded(c tele.Context) error {
	if !b.isAdmin(c.Sender().ID) {
		return nil
	}

	state := b.states.Get(c.Sender().ID)
	if state == nil || state.Step != StepAwaitForward {
		return nil
	}

	msg := c.Message()
	// 检查是否为转发消息（OriginalUnixtime 在隐私设置隐藏来源时仍存在）
	if msg.OriginalChat == nil && msg.OriginalSender == nil && msg.OriginalUnixtime == 0 {
		return c.Reply("❌ 这不是一条转发消息，请转发一条消息给我")
	}

	userID := c.Sender().ID

	// 相册消息处理
	if msg.AlbumID != "" {
		b.states.AddAlbumMessage(userID, msg)
		b.scheduleAlbumFinalize(c, userID)
		return nil // 等待收集完成
	}

	// 单条消息
	b.states.SetForwarded(userID, msg)
	return b.showCategorySelection(c)
}

// scheduleAlbumFinalize 延迟完成相册收集
func (b *Bot) scheduleAlbumFinalize(c tele.Context, userID int64) {
	albumTimersMu.Lock()
	defer albumTimersMu.Unlock()

	// 取消之前的定时器
	if timer, exists := albumTimers[userID]; exists {
		timer.Stop()
	}

	// 设置新定时器
	albumTimers[userID] = time.AfterFunc(albumCollectDelay, func() {
		albumTimersMu.Lock()
		delete(albumTimers, userID)
		albumTimersMu.Unlock()

		b.states.FinalizeAlbum(userID)
		b.showCategorySelectionAsync(c, userID)
	})
}

// showCategorySelection 显示分类选择
func (b *Bot) showCategorySelection(c tele.Context) error {
	categories, err := b.storage.ListCategories()
	if err != nil {
		b.states.Delete(c.Sender().ID)
		return c.Reply(fmt.Sprintf("❌ 获取分类失败: %v", err))
	}

	if len(categories) == 0 {
		b.states.Delete(c.Sender().ID)
		return c.Reply("❌ 暂无分类，请先使用 /cat_add 创建分类")
	}

	state := b.states.Get(c.Sender().ID)
	msgCount := 1
	if state != nil && len(state.ForwardedMsgs) > 0 {
		msgCount = len(state.ForwardedMsgs)
	}

	keyboard := b.buildCategoryKeyboard(categories)
	if msgCount > 1 {
		return c.Reply(fmt.Sprintf("📁 已收到 %d 条消息（相册），请选择分类:", msgCount), keyboard)
	}
	return c.Reply("📁 请选择分类:", keyboard)
}

// showCategorySelectionAsync 异步显示分类选择（用于定时器回调）
func (b *Bot) showCategorySelectionAsync(c tele.Context, userID int64) {
	categories, err := b.storage.ListCategories()
	if err != nil {
		b.states.Delete(userID)
		c.Bot().Send(c.Chat(), fmt.Sprintf("❌ 获取分类失败: %v", err))
		return
	}

	if len(categories) == 0 {
		b.states.Delete(userID)
		c.Bot().Send(c.Chat(), "❌ 暂无分类，请先使用 /cat_add 创建分类")
		return
	}

	state := b.states.Get(userID)
	msgCount := 1
	if state != nil && len(state.ForwardedMsgs) > 0 {
		msgCount = len(state.ForwardedMsgs)
	}

	keyboard := b.buildCategoryKeyboard(categories)
	if msgCount > 1 {
		c.Bot().Send(c.Chat(), fmt.Sprintf("📁 已收到 %d 条消息（相册），请选择分类:", msgCount), keyboard)
	} else {
		c.Bot().Send(c.Chat(), "📁 请选择分类:", keyboard)
	}
}

func (b *Bot) buildCategoryKeyboard(categories []storage.Category) *tele.ReplyMarkup {
	menu := &tele.ReplyMarkup{}
	var rows []tele.Row

	var currentRow []tele.Btn
	for _, cat := range categories {
		btn := menu.Data(cat.Name, cbPrefixCat+cat.Name)
		currentRow = append(currentRow, btn)

		if len(currentRow) == 3 {
			rows = append(rows, menu.Row(currentRow...))
			currentRow = nil
		}
	}

	if len(currentRow) > 0 {
		rows = append(rows, menu.Row(currentRow...))
	}

	cancelBtn := menu.Data("❌ 取消", cbCancel)
	rows = append(rows, menu.Row(cancelBtn))

	menu.Inline(rows...)
	return menu
}

func (b *Bot) handleCallback(c tele.Context) error {
	if !b.isAdmin(c.Sender().ID) {
		return c.Respond(&tele.CallbackResponse{Text: "无权限"})
	}

	// telebot v3 会在 data 前加 \f 前缀，需要去掉
	data := strings.TrimPrefix(c.Callback().Data, "\f")
	userID := c.Sender().ID

	switch {
	case data == cbCancel:
		return b.handleCancelCallback(c, userID)

	case strings.HasPrefix(data, cbPrefixCat):
		category := strings.TrimPrefix(data, cbPrefixCat)
		return b.handleCategoryCallback(c, userID, category)

	case strings.HasPrefix(data, cbPrefixTitle):
		action := strings.TrimPrefix(data, cbPrefixTitle)
		return b.handleTitleCallback(c, userID, action)

	case strings.HasPrefix(data, cbPrefixConfirm):
		action := strings.TrimPrefix(data, cbPrefixConfirm)
		return b.handleConfirmCallback(c, userID, action)

	case strings.HasPrefix(data, cbPrefixDelWithMsg):
		entryID := strings.TrimPrefix(data, cbPrefixDelWithMsg)
		return b.handleDeleteEntryCallback(c, entryID, true)

	case strings.HasPrefix(data, cbPrefixDelOnlyToc):
		entryID := strings.TrimPrefix(data, cbPrefixDelOnlyToc)
		return b.handleDeleteEntryCallback(c, entryID, false)
	}

	return c.Respond()
}

func (b *Bot) handleCancelCallback(c tele.Context, userID int64) error {
	b.states.Delete(userID)
	c.Edit("❌ 已取消")
	return c.Respond(&tele.CallbackResponse{Text: "已取消"})
}

func (b *Bot) handleTitleCallback(c tele.Context, userID int64, action string) error {
	state := b.states.Get(userID)
	if state == nil || state.Step != StepAwaitTitle {
		return c.Respond(&tele.CallbackResponse{Text: "会话已过期"})
	}

	if action == "default" {
		// 使用默认标题
		title := extractTitle(state.ForwardedMsg)
		b.states.SetTitle(userID, title)
		return b.showConfirmation(c, state, title)
	}

	// 自定义标题 - 提示用户输入
	c.Edit("✏️ 请发送新标题:")
	return c.Respond()
}

func (b *Bot) handleTitleInput(c tele.Context) error {
	state := b.states.Get(c.Sender().ID)
	if state == nil || state.Step != StepAwaitTitle {
		return nil
	}

	title := strings.TrimSpace(c.Message().Text)
	if title == "" {
		return c.Reply("❌ 标题不能为空，请重新输入:")
	}

	if len(title) > 50 {
		title = title[:47] + "..."
	}

	b.states.SetTitle(c.Sender().ID, title)
	return b.showConfirmationMsg(c, state, title)
}

func (b *Bot) showConfirmation(c tele.Context, state *PostState, title string) error {
	channelName := "未知频道"
	if state.ForwardedMsg.OriginalChat != nil {
		channelName = state.ForwardedMsg.OriginalChat.Title
	}

	menu := &tele.ReplyMarkup{}
	confirmBtn := menu.Data("✅ 确认添加", cbPrefixConfirm+"yes")
	cancelBtn := menu.Data("❌ 取消", cbCancel)
	menu.Inline(menu.Row(confirmBtn, cancelBtn))

	text := fmt.Sprintf("📋 确认添加?\n\n频道: %s\n分类: %s\n标题: %s", channelName, state.SelectedCat, title)
	c.Edit(text, menu)
	return c.Respond()
}

func (b *Bot) showConfirmationMsg(c tele.Context, state *PostState, title string) error {
	channelName := "未知频道"
	if state.ForwardedMsg.OriginalChat != nil {
		channelName = state.ForwardedMsg.OriginalChat.Title
	}

	menu := &tele.ReplyMarkup{}
	confirmBtn := menu.Data("✅ 确认添加", cbPrefixConfirm+"yes")
	cancelBtn := menu.Data("❌ 取消", cbCancel)
	menu.Inline(menu.Row(confirmBtn, cancelBtn))

	text := fmt.Sprintf("📋 确认添加?\n\n频道: %s\n分类: %s\n标题: %s", channelName, state.SelectedCat, title)
	return c.Reply(text, menu)
}

func (b *Bot) handleCategoryCallback(c tele.Context, userID int64, category string) error {
	state := b.states.Get(userID)
	if state == nil || state.Step != StepAwaitCategory {
		return c.Respond(&tele.CallbackResponse{Text: "会话已过期"})
	}

	b.states.SetCategory(userID, category)

	// 提取默认标题
	defaultTitle := extractTitle(state.ForwardedMsg)

	menu := &tele.ReplyMarkup{}
	useDefaultBtn := menu.Data("✅ 使用此标题", cbPrefixTitle+"default")
	customBtn := menu.Data("✏️ 自定义标题", cbPrefixTitle+"custom")
	cancelBtn := menu.Data("❌ 取消", cbCancel)
	menu.Inline(
		menu.Row(useDefaultBtn),
		menu.Row(customBtn),
		menu.Row(cancelBtn),
	)

	text := fmt.Sprintf("📝 确认标题\n\n分类: %s\n标题: %s\n\n使用此标题或自定义?", category, defaultTitle)
	c.Edit(text, menu)
	return c.Respond()
}

func (b *Bot) handleConfirmCallback(c tele.Context, userID int64, action string) error {
	if action != "yes" {
		return b.handleCancelCallback(c, userID)
	}

	state := b.states.Get(userID)
	if state == nil || state.Step != StepAwaitConfirm {
		return c.Respond(&tele.CallbackResponse{Text: "会话已过期"})
	}

	defer b.states.Delete(userID)

	title := state.Title
	channel := &tele.Chat{ID: b.cfg.Channel.ID}

	var channelMsg *tele.Message
	var err error

	// 相册消息
	if len(state.ForwardedMsgs) > 1 {
		channelMsg, err = b.sendAlbumCopy(channel, state.ForwardedMsgs)
	} else {
		// 单条消息
		channelMsg, err = b.sendMessageCopy(channel, state.ForwardedMsg)
	}

	if err != nil {
		c.Edit(fmt.Sprintf("❌ 发送到频道失败: %v", err))
		return c.Respond(&tele.CallbackResponse{Text: "发送失败"})
	}

	channelLink := b.buildChannelLink(channelMsg.ID)
	directLink := extractDirectLinkFromState(state)

	entry, err := b.storage.CreateEntry(state.SelectedCat, title, channelLink, directLink)
	if err != nil {
		c.Edit(fmt.Sprintf("❌ 保存失败: %v", err))
		return c.Respond(&tele.CallbackResponse{Text: "保存失败"})
	}

	b.toc.TriggerUpdate()

	text := fmt.Sprintf("✅ 已添加\n\nID: %s\n分类: %s\n标题: %s", entry.ID, entry.Category, entry.Title)
	c.Edit(text)
	return c.Respond(&tele.CallbackResponse{Text: "添加成功"})
}

// sendMessageCopy 复制消息内容发送（使用 copyMessage API 保留原格式）
func (b *Bot) sendMessageCopy(to *tele.Chat, msg *tele.Message) (*tele.Message, error) {
	// 使用 Copy 方法，完整保留原消息的 entities（代码块、粗体、斜体等格式）
	return b.bot.Copy(to, msg)
}

// sendAlbumCopy 复制相册发送到频道，返回第一条消息
func (b *Bot) sendAlbumCopy(to *tele.Chat, msgs []*tele.Message) (*tele.Message, error) {
	if len(msgs) == 0 {
		return nil, fmt.Errorf("相册为空")
	}

	// 转换为 Editable 接口切片
	editables := make([]tele.Editable, len(msgs))
	for i, msg := range msgs {
		editables[i] = msg
	}

	// 使用 CopyMany 保留原格式（代码块、粗体等 entities）
	sentMsgs, err := b.bot.CopyMany(to, editables)
	if err != nil {
		return nil, err
	}

	if len(sentMsgs) == 0 {
		return nil, fmt.Errorf("发送相册失败")
	}

	return &sentMsgs[0], nil
}

func (b *Bot) buildChannelLink(msgID int) string {
	// 尝试获取频道信息，检查是否为公开频道
	chat, err := b.bot.ChatByID(b.cfg.Channel.ID)
	if err == nil && chat.Username != "" {
		return fmt.Sprintf("https://t.me/%s/%d", chat.Username, msgID)
	}

	// 私有频道 fallback
	chatID := b.cfg.Channel.ID
	if chatID < 0 {
		chatID = -chatID - 1000000000000
	}
	return fmt.Sprintf("https://t.me/c/%d/%d", chatID, msgID)
}

func extractTitle(msg *tele.Message) string {
	text := msg.Text
	if text == "" {
		text = msg.Caption
	}

	lines := strings.Split(text, "\n")
	title := strings.TrimSpace(lines[0])

	if len(title) > 50 {
		title = title[:47] + "..."
	}

	if title == "" {
		title = "无标题"
	}

	return title
}

func extractDirectLinkFromMessages(msgs []*tele.Message) string {
	for _, msg := range msgs {
		if msg == nil {
			continue
		}
		if link := extractDirectLink(msg); link != "" {
			return link
		}
	}
	return ""
}

func extractDirectLinkFromState(state *PostState) string {
	if state == nil {
		return ""
	}
	if link := extractDirectLink(state.ForwardedMsg); link != "" {
		return link
	}
	return extractDirectLinkFromMessages(state.ForwardedMsgs)
}

func extractDirectLink(msg *tele.Message) string {
	if msg == nil {
		return ""
	}

	for _, entity := range msg.Entities {
		if entity.Type == tele.EntityTextLink && entity.URL != "" {
			return entity.URL
		}
	}
	for _, entity := range msg.CaptionEntities {
		if entity.Type == tele.EntityTextLink && entity.URL != "" {
			return entity.URL
		}
	}

	for _, text := range []string{msg.Text, msg.Caption} {
		if text == "" {
			continue
		}
		if match := directURLPattern.FindString(text); match != "" {
			return match
		}
	}

	return ""
}

func buildMessageLink(msg *tele.Message) string {
	if msg.OriginalChat == nil {
		return ""
	}

	chat := msg.OriginalChat
	msgID := msg.OriginalMessageID
	if msgID == 0 {
		msgID = msg.ID
	}

	if chat.Username != "" {
		return fmt.Sprintf("https://t.me/%s/%d", chat.Username, msgID)
	}

	chatID := chat.ID
	if chatID < 0 {
		chatID = -chatID - 1000000000000
	}
	return fmt.Sprintf("https://t.me/c/%d/%d", chatID, msgID)
}
