package service

import (
	"fmt"

	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/model"
)

// CheckInEnergy 签到获得域能（LV0 用户不调用此方法）
func (s *EnergyService) CheckInEnergy(userID uint) error {
	if err := s.repo.AddEnergy(userID, EnergyCheckIn); err != nil {
		return fmt.Errorf("增加签到域能失败: %w", err)
	}

	log := &model.EnergyLog{
		UserID:      userID,
		Amount:      EnergyCheckIn,
		Type:        model.EnergyTypeSignIn,
		Description: "每日签到 +1.0 域能",
	}
	return s.repo.CreateEnergyLog(log)
}

// DeductOnRename 改名扣域能（首次改名免费，不调用此方法）
// 事务包裹：扣用户域能 + 入公户 + 写流水
func (s *EnergyService) DeductOnRename(userID uint) error {
	return s.repo.Transaction(func(txRepo EnergyStore, txFundRepo FundStore) error {
		// 检查域能余额（非 owner 需 ≥ 0）
		user, err := txRepo.FindUserByID(userID)
		if err != nil {
			return fmt.Errorf("查询用户失败: %w", err)
		}
		if user.Role != model.RoleOwner && user.Energy+EnergyRename < 0 {
			return common.ErrInsufficientEnergy
		}

		if err := txRepo.AddEnergy(userID, EnergyRename); err != nil {
			return fmt.Errorf("扣减改名域能失败: %w", err)
		}

		// 公户入账
		if txFundRepo != nil {
			if err := txFundRepo.IncrBalance(-EnergyRename); err != nil { // EnergyRename = -60，入公户 +60
				return fmt.Errorf("公户入账失败: %w", err)
			}
			fundLog := &model.FundLog{
				Amount:      -EnergyRename,
				Type:        model.FundTypeRenameDeduction,
				RelatedType: "user",
				RelatedID:   userID,
				Description: fmt.Sprintf("用户 uid=%d 改名消耗 6.0 域能", userID),
			}
			if err := txFundRepo.CreateLog(fundLog); err != nil {
				return fmt.Errorf("创建公户流水失败: %w", err)
			}
		}

		log := &model.EnergyLog{
			UserID:      userID,
			Amount:      EnergyRename,
			Type:        model.EnergyTypeRename,
			Description: "改名消耗 6.0 域能",
		}
		return txRepo.CreateEnergyLog(log)
	})
}

// RefundOnRenameReject 改名审核被拒，从公户返还域能
func (s *EnergyService) RefundOnRenameReject(userID uint) error {
	return s.repo.Transaction(func(txRepo EnergyStore, txFundRepo FundStore) error {
		// 从公户支出（允许透支）
		if txFundRepo != nil {
			if err := txFundRepo.IncrBalance(-EnergyRenameRefund); err != nil {
				return fmt.Errorf("公户出账失败: %w", err)
			}
			fundLog := &model.FundLog{
				Amount:      -EnergyRenameRefund,
				Type:        model.FundTypeRenameRefund,
				RelatedType: "user",
				RelatedID:   userID,
				Description: fmt.Sprintf("用户 uid=%d 改名审核被拒，返还 6.0 域能", userID),
			}
			if err := txFundRepo.CreateLog(fundLog); err != nil {
				return fmt.Errorf("创建公户流水失败: %w", err)
			}
		}

		if err := txRepo.AddEnergy(userID, EnergyRenameRefund); err != nil {
			return fmt.Errorf("返还改名域能失败: %w", err)
		}

		log := &model.EnergyLog{
			UserID:      userID,
			Amount:      EnergyRenameRefund,
			Type:        model.EnergyTypeRenameRefund,
			Description: "改名审核被拒，返还 6.0 域能",
		}
		return txRepo.CreateEnergyLog(log)
	})
}

// DeductOnDeletePost 删稿扣域能（扣文章作者的域能，无视负数）
// 事务包裹：扣用户域能 + 入公户 + 写流水
func (s *EnergyService) DeductOnDeletePost(authorUserID uint, postID uint) error {
	return s.repo.Transaction(func(txRepo EnergyStore, txFundRepo FundStore) error {
		if err := txRepo.AddEnergy(authorUserID, EnergyDeletePost); err != nil {
			return fmt.Errorf("扣减删稿域能失败: %w", err)
		}

		// 公户入账
		if txFundRepo != nil {
			if err := txFundRepo.IncrBalance(-EnergyDeletePost); err != nil { // EnergyDeletePost = -20，入公户 +20
				return fmt.Errorf("公户入账失败: %w", err)
			}
			fundLog := &model.FundLog{
				Amount:      -EnergyDeletePost,
				Type:        model.FundTypeDeletePost,
				RelatedType: "post",
				RelatedID:   postID,
				Description: fmt.Sprintf("用户 uid=%d 删除文章 #%d 消耗 2.0 域能", authorUserID, postID),
			}
			if err := txFundRepo.CreateLog(fundLog); err != nil {
				return fmt.Errorf("创建公户流水失败: %w", err)
			}
		}

		log := &model.EnergyLog{
			UserID:      authorUserID,
			Amount:      EnergyDeletePost,
			Type:        model.EnergyTypeDeletePost,
			RelatedType: "post",
			RelatedID:   postID,
			Description: "删除文章消耗 2.0 域能",
		}
		return txRepo.CreateEnergyLog(log)
	})
}
