// Package shop 提供店铺通知接收人的 PostgreSQL Adapter。
package shop

import (
	"context"
	"sort"

	"gorm.io/gorm"

	shopapp "github.com/break/junhong_cmp_fiber/internal/application/shop"
	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
)

// RecipientResolver 按店铺当前独立归属解析主账号和可用平台业务员。
type RecipientResolver struct {
	db *gorm.DB
}

var _ shopapp.NotificationRecipientResolver = (*RecipientResolver)(nil)

// NewRecipientResolver 创建店铺通知接收人解析 Adapter。
func NewRecipientResolver(db *gorm.DB) *RecipientResolver {
	return &RecipientResolver{db: db}
}

// ResolveNotificationRecipients 返回启用的店铺主账号和当前可用业务员账号 ID。
//
// 解析只读取目标店铺当前保存的业务员 ID，不读取父店铺、祖先店铺或创建人。
func (r *RecipientResolver) ResolveNotificationRecipients(ctx context.Context, shopID uint) ([]uint, error) {
	if shopID == 0 {
		return nil, errors.New(errors.CodeInvalidParam)
	}
	var target struct {
		BusinessOwnerAccountID *uint
	}
	err := r.db.WithContext(ctx).Model(&model.Shop{}).
		Select("business_owner_account_id").Where("id = ?", shopID).Take(&target).Error
	if err == gorm.ErrRecordNotFound {
		return []uint{}, nil
	}
	if err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询店铺通知归属失败")
	}

	query := r.db.WithContext(ctx).Model(&model.Account{}).
		Select("id").
		Where("status = ? AND shop_id = ? AND is_primary = ? AND user_type = ?",
			constants.StatusEnabled, shopID, true, constants.UserTypeAgent)
	if target.BusinessOwnerAccountID != nil {
		query = query.Or("id = ? AND status = ? AND user_type = ?",
			*target.BusinessOwnerAccountID, constants.StatusEnabled, constants.UserTypePlatform)
	}
	var accounts []model.Account
	if err := query.Find(&accounts).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询店铺通知接收人失败")
	}

	ids := make([]uint, 0, len(accounts))
	seen := make(map[uint]struct{}, len(accounts))
	for _, account := range accounts {
		if _, exists := seen[account.ID]; exists {
			continue
		}
		seen[account.ID] = struct{}{}
		ids = append(ids, account.ID)
	}
	sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
	return ids, nil
}
