package withdrawal

import (
	"context"
	"errors"
	"fmt"
	"time"

	"hfb_sys/backend/internal/model"
	"hfb_sys/backend/internal/modules/wallet"

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

// 管理员查询提现列表
func (r *Repository) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
	db := r.db.WithContext(ctx).Model(&model.WithdrawalRequest{})

	if query.Status != "" {
		db = db.Where("status = ?", query.Status)
	}
	if query.UserID > 0 {
		db = db.Where("user_id = ?", query.UserID)
	}

	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, err
	}

	offset := (query.Page - 1) * query.Size
	var withdrawals []model.WithdrawalRequest
	if err := db.Order("created_at DESC").
		Offset(offset).Limit(query.Size).
		Find(&withdrawals).Error; err != nil {
		return nil, err
	}

	items := make([]WithdrawalDetailDTO, 0, len(withdrawals))
	for _, w := range withdrawals {
		dto, err := r.toDetailDTO(ctx, w)
		if err != nil {
			continue
		}
		items = append(items, *dto)
	}

	return &AdminPaginatedResult{
		Items:    items,
		Total:    total,
		Page:     query.Page,
		PageSize: query.Size,
	}, nil
}

// 管理员查询提现详情

// 管理员查询提现详情
func (r *Repository) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
	var withdrawal model.WithdrawalRequest
	if err := r.db.WithContext(ctx).First(&withdrawal, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, ErrWithdrawalNotFound
		}
		return nil, err
	}
	return r.toDetailDTO(ctx, withdrawal)
}

// 管理员审核提现

// 管理员审核提现
func (r *Repository) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
	err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var withdrawal model.WithdrawalRequest
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&withdrawal, id).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return ErrWithdrawalNotFound
			}
			return err
		}

		// 事务内加行锁后重新校验，只有待审核状态可以审核，避免并发重复处理
		if withdrawal.Status != "pending" {
			return ErrWithdrawalLocked
		}

		now := time.Now()
		approved := *req.Approved
		if approved {
			// 审核通过，进入处理中状态
			withdrawal.Status = "processing"
		} else {
			// 审核拒绝，解冻余额
			withdrawal.Status = "rejected"
		}
		withdrawal.ReviewedBy = &adminID
		withdrawal.ReviewedAt = &now
		withdrawal.ReviewRemark = req.Remark

		if err := tx.Save(&withdrawal).Error; err != nil {
			return err
		}

		// 如果拒绝，解冻余额
		if !approved {
			if err := wallet.AppendEntries(tx, wallet.Entry{
				UserID:      withdrawal.UserID,
				Direction:   "out",
				AmountCent:  withdrawal.AmountCent,
				BalanceType: "frozen",
				BizType:     "withdraw_reject",
				BizNo:       withdrawal.WithdrawNo,
				Remark:      fmt.Sprintf("提现被拒绝: %s", req.Remark),
			}, wallet.Entry{
				UserID:      withdrawal.UserID,
				Direction:   "in",
				AmountCent:  withdrawal.AmountCent,
				BalanceType: "available",
				BizType:     "withdraw_reject",
				BizNo:       withdrawal.WithdrawNo,
				Remark:      fmt.Sprintf("提现被拒绝: %s", req.Remark),
			}); err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return r.AdminFindByID(ctx, id)
}

// 管理员确认打款

// 管理员确认打款
func (r *Repository) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
	err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var withdrawal model.WithdrawalRequest
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&withdrawal, id).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return ErrWithdrawalNotFound
			}
			return err
		}

		// 事务内加行锁后重新校验，只有处理中状态可以确认打款，避免并发重复扣减冻结余额
		if withdrawal.Status != "processing" {
			return ErrWithdrawalLocked
		}

		now := time.Now()
		withdrawal.Status = "completed"
		withdrawal.PaidBy = &adminID
		withdrawal.PaidAt = &now
		withdrawal.PaymentProofURL = req.PaymentProofURL
		withdrawal.PaymentRemark = req.Remark

		if err := tx.Save(&withdrawal).Error; err != nil {
			return err
		}

		// 扣除冻结余额
		if err := wallet.AppendEntries(tx, wallet.Entry{
			UserID:      withdrawal.UserID,
			Direction:   "out",
			AmountCent:  withdrawal.AmountCent,
			BalanceType: "frozen",
			BizType:     "withdraw_complete",
			BizNo:       withdrawal.WithdrawNo,
			Remark:      "提现完成",
		}); err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return r.AdminFindByID(ctx, id)
}

// 转换为用户DTO
