package chat

import (
	"context"
	"errors"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"hfb_sys/backend/internal/model"
)

// QrCodeStatus 二维码状态常量
const (
	QrCodeStatusUnused   = "unused"
	QrCodeStatusUsed     = "used"
	QrCodeStatusDisabled = "disabled"
)

var (
	ErrQrCodeNotFound     = errors.New("二维码不存在")
	ErrQrCodeCannotDelete = errors.New("已使用的二维码不能删除")
)

// CreateQrCodeRequest 创建二维码请求
type CreateQrCodeRequest struct {
	ImageURL  string     `json:"image_url" binding:"required"`
	Note      string     `json:"note"`
	ExpiresAt *time.Time `json:"expires_at"`
}

// UpdateQrCodeRequest 更新二维码请求
type UpdateQrCodeRequest struct {
	Note      *string    `json:"note"`
	Status    *string    `json:"status"`
	ExpiresAt *time.Time `json:"expires_at"`
}

// QrCodeListRequest 列表查询请求
type QrCodeListRequest struct {
	Status string `form:"status"`
	Page   int    `form:"page"`
	Limit  int    `form:"limit"`
}

// QrCodeStats 二维码统计
type QrCodeStats struct {
	UnusedCount   int64 `json:"unused_count"`
	UsedCount     int64 `json:"used_count"`
	DisabledCount int64 `json:"disabled_count"`
	TotalCount    int64 `json:"total_count"`
}

// CreateQrCode 创建二维码
func (r *Repository) CreateQrCode(ctx context.Context, adminID uint64, req CreateQrCodeRequest) (*model.ChatQrCode, error) {
	qrcode := model.ChatQrCode{
		ImageURL:  req.ImageURL,
		Status:    QrCodeStatusUnused,
		CreatedBy: adminID,
		Note:      req.Note,
		ExpiresAt: req.ExpiresAt,
	}

	// 如果未指定过期时间，默认7天后过期
	if qrcode.ExpiresAt == nil {
		expires := time.Now().Add(7 * 24 * time.Hour)
		qrcode.ExpiresAt = &expires
	}

	if err := r.db.WithContext(ctx).Create(&qrcode).Error; err != nil {
		return nil, err
	}

	return &qrcode, nil
}

// ListQrCodes 列表查询二维码
func (r *Repository) ListQrCodes(ctx context.Context, req QrCodeListRequest) ([]model.ChatQrCode, int64, error) {
	if req.Page < 1 {
		req.Page = 1
	}
	if req.Limit < 1 || req.Limit > 100 {
		req.Limit = 20
	}

	query := r.db.WithContext(ctx).Model(&model.ChatQrCode{})

	// 状态过滤
	if req.Status != "" {
		query = query.Where("status = ?", req.Status)
	}

	// 统计总数
	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 查询列表
	var qrcodes []model.ChatQrCode
	offset := (req.Page - 1) * req.Limit
	if err := query.Order("id DESC").Offset(offset).Limit(req.Limit).Find(&qrcodes).Error; err != nil {
		return nil, 0, err
	}

	return qrcodes, total, nil
}

// GetQrCodeStats 获取二维码统计信息
func (r *Repository) GetQrCodeStats(ctx context.Context) (*QrCodeStats, error) {
	stats := &QrCodeStats{}

	// 统计各状态数量
	type CountResult struct {
		Status string
		Count  int64
	}
	var results []CountResult

	if err := r.db.WithContext(ctx).
		Model(&model.ChatQrCode{}).
		Select("status, COUNT(*) as count").
		Group("status").
		Find(&results).Error; err != nil {
		return nil, err
	}

	for _, r := range results {
		stats.TotalCount += r.Count
		switch r.Status {
		case QrCodeStatusUnused:
			stats.UnusedCount = r.Count
		case QrCodeStatusUsed:
			stats.UsedCount = r.Count
		case QrCodeStatusDisabled:
			stats.DisabledCount = r.Count
		}
	}

	return stats, nil
}

// UpdateQrCode 更新二维码
func (r *Repository) UpdateQrCode(ctx context.Context, id uint64, req UpdateQrCodeRequest) error {
	updates := make(map[string]interface{})

	if req.Note != nil {
		updates["note"] = *req.Note
	}
	if req.Status != nil {
		// 校验状态值
		if *req.Status != QrCodeStatusUnused && *req.Status != QrCodeStatusUsed && *req.Status != QrCodeStatusDisabled {
			return errors.New("无效的状态值")
		}
		updates["status"] = *req.Status
	}
	if req.ExpiresAt != nil {
		updates["expires_at"] = req.ExpiresAt
	}

	if len(updates) == 0 {
		return nil
	}

	result := r.db.WithContext(ctx).Model(&model.ChatQrCode{}).Where("id = ?", id).Updates(updates)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return ErrQrCodeNotFound
	}

	return nil
}

// DeleteQrCode 删除二维码(仅未使用的可删除)
func (r *Repository) DeleteQrCode(ctx context.Context, id uint64) error {
	var qrcode model.ChatQrCode
	if err := r.db.WithContext(ctx).First(&qrcode, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ErrQrCodeNotFound
		}
		return err
	}

	// 已使用的不能删除
	if qrcode.Status == QrCodeStatusUsed {
		return ErrQrCodeCannotDelete
	}

	return r.db.WithContext(ctx).Delete(&qrcode).Error
}

// fetchUnusedQrCode 获取一个未使用且未过期的二维码(带行锁)
func (r *Repository) fetchUnusedQrCode(tx *gorm.DB) (*model.ChatQrCode, error) {
	var qrcode model.ChatQrCode
	now := time.Now()

	err := tx.Where("status = ?", QrCodeStatusUnused).
		Where("expires_at IS NULL OR expires_at > ?", now).
		Order("id ASC").
		Limit(1).
		Clauses(clause.Locking{Strength: "UPDATE"}).
		First(&qrcode).Error

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil // 无可用二维码,返回 nil 而非错误
		}
		return nil, err
	}

	return &qrcode, nil
}

// markQrCodeAsUsed 标记二维码为已使用
func (r *Repository) markQrCodeAsUsed(tx *gorm.DB, qrcodeID uint64, conversationID uint64) error {
	now := time.Now()
	return tx.Model(&model.ChatQrCode{}).
		Where("id = ?", qrcodeID).
		Updates(map[string]interface{}{
			"status":          QrCodeStatusUsed,
			"conversation_id": conversationID,
			"used_at":         now,
		}).Error
}
