package feishu

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"ops-assistant/internal/channel"
	"ops-assistant/internal/core/ops"
	"ops-assistant/internal/service"
	"ops-assistant/models"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// DefaultUserID 统一用户ID，使所有平台共享同一份账本
const DefaultUserID int64 = 1

type Bot struct {
	db                *gorm.DB
	finance           *service.FinanceService
	opsSvc            *ops.Service
	appID             string
	appSecret         string
	verificationToken string
	encryptKey        string
}

func NewBot(db *gorm.DB, finance *service.FinanceService, opsSvc *ops.Service, appID, appSecret, verificationToken, encryptKey string) *Bot {
	return &Bot{
		db:                db,
		finance:           finance,
		opsSvc:            opsSvc,
		appID:             appID,
		appSecret:         appSecret,
		verificationToken: verificationToken,
		encryptKey:        encryptKey,
	}
}

func (b *Bot) Start(ctx context.Context) {
	log.Printf("🚀 Feishu Bot 已启用 app_id=%s", maskID(b.appID))
	<-ctx.Done()
	log.Printf("⏳ Feishu Bot 已停止")
}

func (b *Bot) RegisterRoutes(r *gin.Engine) {
	r.POST("/webhook/feishu", b.handleWebhook)
}

func (b *Bot) handleWebhook(c *gin.Context) {
	body, err := io.ReadAll(io.LimitReader(c.Request.Body, 1<<20))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
		return
	}

	// 统一走 channel 包解析，便于后续扩展验签/解密
	msg, verifyChallenge, err := channel.ParseFeishuInbound(body, b.verificationToken)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	if verifyChallenge != "" {
		c.JSON(http.StatusOK, gin.H{"challenge": verifyChallenge})
		return
	}
	if msg == nil {
		c.JSON(http.StatusOK, gin.H{"code": 0})
		return
	}

	// 幂等去重
	var existed models.MessageDedup
	if err := b.db.Where("platform = ? AND event_id = ?", "feishu", msg.EventID).First(&existed).Error; err == nil {
		c.JSON(http.StatusOK, gin.H{"code": 0})
		return
	}
	_ = b.db.Create(&models.MessageDedup{Platform: "feishu", EventID: msg.EventID, ProcessedAt: time.Now()}).Error

	reply := b.handleText(msg.Text)
	if reply != "" && msg.UserID != "" {
		tk, err := channel.GetFeishuTenantToken(c.Request.Context(), b.appID, b.appSecret)
		if err == nil {
			_ = channel.SendFeishuText(c.Request.Context(), tk, msg.UserID, reply)
		}
	}

	c.JSON(http.StatusOK, gin.H{"code": 0})
}

func (b *Bot) handleText(text string) string {
	trim := strings.TrimSpace(text)
	if b.opsSvc != nil {
		if handled, out := b.opsSvc.Handle(DefaultUserID, trim); handled {
			return out
		}
	}
	switch trim {
	case "帮助", "help", "/help", "菜单", "功能", "/start":
		return "🛠️ Ops-Assistant\n\n直接发送消费描述即可记账：\n• 午饭 25元\n• 打车 ¥30\n\n📋 命令：记录/查看、今日/今天、统计"
	case "查看", "记录", "列表", "最近":
		items, err := b.finance.GetTransactions(DefaultUserID, 10)
		if err != nil {
			return "❌ 查询失败"
		}
		if len(items) == 0 {
			return "📭 暂无记录"
		}
		var sb strings.Builder
		sb.WriteString("📋 最近记录：\n\n")
		for _, item := range items {
			sb.WriteString(fmt.Sprintf("%s %s %.2f元\n", item.Date, item.Category, item.AmountYuan()))
		}
		return sb.String()
	}

	amount, category, err := b.finance.AddTransaction(DefaultUserID, trim)
	if err != nil {
		return "❌ 记账失败，请稍后重试"
	}
	if amount == 0 {
		return "📍 没看到金额，这笔花了多少钱？"
	}
	return fmt.Sprintf("✅ 已记入【%s】：%.2f元\n📝 备注：%s", category, float64(amount)/100.0, trim)
}

func maskID(s string) string {
	if len(s) <= 6 {
		return "***"
	}
	return s[:3] + "***" + s[len(s)-3:]
}
