package commission_withdrawal_setting

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type Service struct {
	db                               *gorm.DB
	accountStore                     *postgres.AccountStore
	commissionWithdrawalSettingStore *postgres.CommissionWithdrawalSettingStore
}

func New(
	db *gorm.DB,
	accountStore *postgres.AccountStore,
	commissionWithdrawalSettingStore *postgres.CommissionWithdrawalSettingStore,
) *Service {
	return &Service{
		db:                               db,
		accountStore:                     accountStore,
		commissionWithdrawalSettingStore: commissionWithdrawalSettingStore,
	}
}

func (s *Service) Create(ctx context.Context, req *dto.CreateWithdrawalSettingReq) (*dto.WithdrawalSettingItem, error) {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	setting := &model.CommissionWithdrawalSetting{
		DailyWithdrawalLimit: req.DailyWithdrawalLimit,
		MinWithdrawalAmount:  req.MinWithdrawalAmount,
		FeeRate:              req.FeeRate,
		IsActive:             true,
	}
	setting.Creator = currentUserID
	setting.Updater = currentUserID

	err := s.db.Transaction(func(tx *gorm.DB) error {
		// 先锁定当前活跃记录，防止并发激活导致多条 is_active=true
		var current model.CommissionWithdrawalSetting
		tx.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("is_active = ?", true).
			First(&current)

		if err := s.commissionWithdrawalSettingStore.DeactivateCurrentWithTx(ctx, tx); err != nil {
			return errors.Wrap(errors.CodeInternalError, err, "失效旧配置失败")
		}
		if err := s.commissionWithdrawalSettingStore.CreateWithTx(ctx, tx, setting); err != nil {
			return errors.Wrap(errors.CodeInternalError, err, "创建配置失败")
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	creatorName := ""
	if creator, err := s.accountStore.GetByID(ctx, currentUserID); err == nil {
		creatorName = creator.Username
	}

	return &dto.WithdrawalSettingItem{
		ID:                   setting.ID,
		DailyWithdrawalLimit: setting.DailyWithdrawalLimit,
		MinWithdrawalAmount:  setting.MinWithdrawalAmount,
		FeeRate:              setting.FeeRate,
		ArrivalDays:          setting.ArrivalDays,
		IsActive:             setting.IsActive,
		CreatorID:            setting.Creator,
		CreatorName:          creatorName,
		CreatedAt:            setting.CreatedAt.Format("2006-01-02 15:04:05"),
	}, nil
}

func (s *Service) List(ctx context.Context, req *dto.WithdrawalSettingListReq) (*dto.WithdrawalSettingPageResult, error) {
	opts := &store.QueryOptions{
		Page:     req.Page,
		PageSize: req.PageSize,
	}
	if opts.Page == 0 {
		opts.Page = 1
	}
	if opts.PageSize == 0 {
		opts.PageSize = constants.DefaultPageSize
	}

	settings, total, err := s.commissionWithdrawalSettingStore.List(ctx, opts)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询配置列表失败")
	}

	creatorIDs := make([]uint, 0)
	for _, setting := range settings {
		if setting.Creator > 0 {
			creatorIDs = append(creatorIDs, setting.Creator)
		}
	}

	creatorMap := make(map[uint]string)
	if len(creatorIDs) > 0 {
		accounts, _ := s.accountStore.GetByIDs(ctx, creatorIDs)
		for _, acc := range accounts {
			creatorMap[acc.ID] = acc.Username
		}
	}

	items := make([]dto.WithdrawalSettingItem, 0, len(settings))
	for _, setting := range settings {
		items = append(items, dto.WithdrawalSettingItem{
			ID:                   setting.ID,
			DailyWithdrawalLimit: setting.DailyWithdrawalLimit,
			MinWithdrawalAmount:  setting.MinWithdrawalAmount,
			FeeRate:              setting.FeeRate,
			ArrivalDays:          setting.ArrivalDays,
			IsActive:             setting.IsActive,
			CreatorID:            setting.Creator,
			CreatorName:          creatorMap[setting.Creator],
			CreatedAt:            setting.CreatedAt.Format("2006-01-02 15:04:05"),
		})
	}

	return &dto.WithdrawalSettingPageResult{
		Items: items,
		Total: total,
		Page:  opts.Page,
		Size:  opts.PageSize,
	}, nil
}

func (s *Service) GetCurrent(ctx context.Context) (*dto.WithdrawalSettingItem, error) {
	setting, err := s.commissionWithdrawalSettingStore.GetCurrent(ctx)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "暂无生效的提现配置")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询当前配置失败")
	}

	creatorName := ""
	if creator, err := s.accountStore.GetByID(ctx, setting.Creator); err == nil {
		creatorName = creator.Username
	}

	return &dto.WithdrawalSettingItem{
		ID:                   setting.ID,
		DailyWithdrawalLimit: setting.DailyWithdrawalLimit,
		MinWithdrawalAmount:  setting.MinWithdrawalAmount,
		FeeRate:              setting.FeeRate,
		ArrivalDays:          setting.ArrivalDays,
		IsActive:             setting.IsActive,
		CreatorID:            setting.Creator,
		CreatorName:          creatorName,
		CreatedAt:            setting.CreatedAt.Format("2006-01-02 15:04:05"),
	}, nil
}
