package order

import (
	"context"
	"time"

	"hfb_sys/backend/internal/model"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// AdminHoldDeposit 客服对进行中订单的押金进行暂扣。
// 暂扣本身不移动任何资金：租客押金全程在支付渠道，系统只记录“暂扣中”标记；
// 待订单结算/取消/关闭/仲裁时，本应原路退还租客的押金部分会被拦截挂起，
// 后续由客服通过 AdminReleaseDeposit 手动原路归还。
func (r *Repository) AdminHoldDeposit(ctx context.Context, adminID uint64, orderID uint64, req AdminActionRequest, meta AuditMeta) error {
	return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var order model.RentalOrder
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
			return err
		}
		if !canHoldDeposit(order) {
			return ErrDepositCannotHold
		}
		beforeStatus := order.DepositHoldStatus
		now := time.Now()
		order.DepositHoldStatus = depositHoldStatusHeld
		order.DepositHoldReason = req.Reason
		order.DepositHeldBy = &adminID
		order.DepositHeldAt = &now
		order.DepositHoldReleasedAt = nil
		if err := appendAuditLog(tx, adminID, "order.deposit_hold", "order", order.ID, meta, map[string]any{
			"order_id":            order.ID,
			"order_no":            order.OrderNo,
			"renter_id":           order.RenterID,
			"reason":              req.Reason,
			"before_hold_status":  beforeStatus,
			"after_hold_status":   order.DepositHoldStatus,
			"deposit_amount_cent": order.DepositAmountCent,
		}); err != nil {
			return err
		}
		return tx.Save(&order).Error
	})
}

// AdminReleaseDeposit 客服手动归还此前暂扣的押金，通过支付渠道原路退回。
// 仅支持归还，不支持扣款（系统内无平台资金池承接扣款）。
func (r *Repository) AdminReleaseDeposit(ctx context.Context, adminID uint64, orderID uint64, req AdminActionRequest, meta AuditMeta) error {
	var refund *refundAction
	err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var order model.RentalOrder
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
			return err
		}
		if order.DepositHoldStatus != depositHoldStatusHeld {
			return ErrDepositNotHeld
		}
		holdAmountCent := order.DepositHoldAmountCent
		if holdAmountCent <= 0 {
			return ErrDepositHoldAmountEmpty
		}
		now := time.Now()
		order.DepositHoldStatus = depositHoldStatusReleased
		order.DepositHoldReleasedAt = &now
		action, err := r.prepareRefund(&order, holdAmountCent, refundBizDeposit, "暂扣押金归还原路退回")
		if err != nil {
			return err
		}
		refund = action
		if err := appendAuditLog(tx, adminID, "order.deposit_release", "order", order.ID, meta, map[string]any{
			"order_id":                 order.ID,
			"order_no":                 order.OrderNo,
			"renter_id":                order.RenterID,
			"reason":                   req.Reason,
			"deposit_hold_amount_cent": holdAmountCent,
		}); err != nil {
			return err
		}
		return tx.Save(&order).Error
	})
	if err != nil {
		return err
	}
	r.startRefundBestEffort(ctx, refund)
	return nil
}

// canHoldDeposit 判断订单当前是否允许暂扣押金：
// 仅进行中（非终态、押金退款尚未发生）且有实付押金、且未处于暂扣态的订单。
func canHoldDeposit(order model.RentalOrder) bool {
	if order.DepositHoldStatus != depositHoldStatusNone {
		return false
	}
	if order.DepositAmountCent <= 0 {
		return false
	}
	switch order.Status {
	case orderStatusPendingHandoff,
		orderStatusRenting,
		orderStatusOverdue,
		orderStatusPendingCheckoutConfirm,
		orderStatusPendingCheckoutAccept,
		orderStatusCheckoutDisputing:
		return true
	default:
		return false
	}
}
