package billing

import (
	"errors"
	"strconv"

	"juhe-factory/api/internal/model"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

// PrechargeGenerationTask creates a task and reserves its full quoted cost in
// the same transaction. A zero price is allowed only when the model has an
// explicit zero-price record; callers must reject a missing price record.
func PrechargeGenerationTask(tx *gorm.DB, task *model.GenerationTask, unitPrice string, quantity int, remark string) error {
	price, err := strconv.ParseFloat(unitPrice, 64)
	if err != nil || price < 0 || quantity <= 0 {
		return errors.New("生成任务价格无效")
	}
	var amount string
	if err := tx.Raw("SELECT round(?::numeric * ?::numeric,2)::text", unitPrice, quantity).Scan(&amount).Error; err != nil {
		return err
	}
	if amount == "" {
		return errors.New("生成任务价格无效")
	}
	task.EstimatedPoints = amount
	task.PrepaidPoints = amount
	if task.ID == uuid.Nil {
		task.ID = uuid.New()
	}

	if amountValue, _ := strconv.ParseFloat(amount, 64); amountValue > 0 {
		if _, err := DebitPoints(tx, task.UserID, amount, "generation_hold", task.ID.String(), remark, "generation:hold:"+task.ID.String()); err != nil {
			return err
		}
	}
	if err := tx.Create(task).Error; err != nil {
		return err
	}
	return nil
}

// RefundGenerationTask refunds a prepaid task exactly once. The caller must
// hold a row lock on task inside the same transaction.
func RefundGenerationTask(tx *gorm.DB, task *model.GenerationTask, remark string) (bool, error) {
	amount, _ := strconv.ParseFloat(task.PrepaidPoints, 64)
	if task.CostRefunded || amount <= 0 {
		return false, nil
	}
	refunded, err := RefundDebit(tx, task.UserID, "generation:hold:"+task.ID.String(), "generation:refund:"+task.ID.String(),
		"generation_refund", task.ID.String(), remark)
	if err != nil {
		return false, err
	}
	task.CostRefunded = true
	return refunded, nil
}
