package admin_order

import (
	"context"
	"database/sql"
	"fmt"
	"time"

	"ycc-server/app/main/api/internal/svc"
	"ycc-server/app/main/api/internal/types"
	"ycc-server/app/main/model"
	"ycc-server/common/xerr"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

const RefundNoPrefix = "refund-"

type AdminRefundOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewAdminRefundOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRefundOrderLogic {
	return &AdminRefundOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq) (resp *types.AdminRefundOrderResp, err error) {
	// 获取并验证订单
	order, err := l.getAndValidateOrder(req.Id, req.RefundAmount)
	if err != nil {
		return nil, err
	}

	// 根据支付平台处理退款
	switch order.PaymentPlatform {
	case model.PaymentPlatformAlipay:
		return l.handleAlipayRefund(order, req)
	case model.PaymentPlatformWechat:
		return l.handleWechatRefund(order, req)
	default:
		return nil, errors.Wrapf(xerr.NewErrMsg("不支持的支付平台"), "AdminRefundOrder, 不支持的支付平台: %s", order.PaymentPlatform)
	}
}

// getAndValidateOrder 获取并验证订单信息
func (l *AdminRefundOrderLogic) getAndValidateOrder(orderId int64, refundAmount float64) (*model.Order, error) {
	order, err := l.svcCtx.OrderModel.FindOne(l.ctx, orderId)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询订单失败 err: %v", err)
	}

	// 检查订单状态
	if order.Status != model.OrderStatusPaid {
		return nil, errors.Wrapf(xerr.NewErrMsg("订单状态不正确，无法退款"), "AdminRefundOrder, 订单状态: %s", order.Status)
	}

	// 检查退款金额
	if refundAmount > order.Amount {
		return nil, errors.Wrapf(xerr.NewErrMsg("退款金额不能大于订单金额"), "AdminRefundOrder, 退款金额: %f, 订单金额: %f", refundAmount, order.Amount)
	}

	return order, nil
}

// handleAlipayRefund 处理支付宝退款
func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
	// 调用支付宝退款接口
	refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.OrderNo, req.RefundAmount)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 支付宝退款失败 err: %v", err)
	}

	refundNo := l.generateRefundNo(order.OrderNo)

	if refundResp.IsSuccess() {
		// 支付宝退款成功，创建成功记录
		err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, refundResp.TradeNo, model.OrderStatusRefunded, model.OrderRefundStatusSuccess)
		if err != nil {
			return nil, err
		}

		return &types.AdminRefundOrderResp{
			Status:   model.OrderStatusRefunded,
			RefundNo: refundNo,
			Amount:   req.RefundAmount,
		}, nil
	} else {
		// 支付宝退款失败，创建失败记录但不更新订单状态
		err = l.createRefundRecordOnly(order, req, refundNo, refundResp.TradeNo, model.OrderRefundStatusFailed)
		if err != nil {
			logx.Errorf("创建退款失败记录时出错: %v", err)
		}
		return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("退款失败: %v", refundResp.Msg)), "AdminRefundOrder, 支付宝退款失败")
	}
}

// handleWechatRefund 处理微信退款
func (l *AdminRefundOrderLogic) handleWechatRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
	// 调用微信退款接口
	err := l.svcCtx.WechatPayService.WeChatRefund(l.ctx, order.OrderNo, req.RefundAmount, order.Amount)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 微信退款失败 err: %v", err)
	}

	// 微信退款是异步的，创建pending状态的退款记录
	refundNo := l.generateRefundNo(order.OrderNo)
	err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", model.OrderStatusRefunding, model.OrderRefundStatusPending)
	if err != nil {
		return nil, err
	}

	return &types.AdminRefundOrderResp{
		Status:   model.OrderRefundStatusPending,
		RefundNo: refundNo,
		Amount:   req.RefundAmount,
	}, nil
}

// createRefundRecordAndUpdateOrder 创建退款记录并更新订单状态
func (l *AdminRefundOrderLogic) createRefundRecordAndUpdateOrder(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, orderStatus, refundStatus string) error {
	return l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		// 创建退款记录
		refund := &model.OrderRefund{
			RefundNo:         refundNo,
			PlatformRefundId: l.createNullString(platformRefundId),
			OrderId:          order.Id,
			UserId:           order.UserId,
			ProductId:        order.ProductId,
			RefundAmount:     req.RefundAmount,
			RefundReason:     l.createNullString(req.RefundReason),
			Status:           refundStatus, // 使用传入的状态，不再硬编码
			RefundTime:       sql.NullTime{Time: time.Now(), Valid: true},
		}

		if _, err := l.svcCtx.OrderRefundModel.Insert(ctx, session, refund); err != nil {
			return fmt.Errorf("创建退款记录失败: %v", err)
		}

		// 更新订单状态
		order.Status = orderStatus
		if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
			return fmt.Errorf("更新订单状态失败: %v", err)
		}

		return nil
	})
}

// createRefundRecordOnly 仅创建退款记录，不更新订单状态（用于退款失败的情况）
func (l *AdminRefundOrderLogic) createRefundRecordOnly(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, refundStatus string) error {
	refund := &model.OrderRefund{
		RefundNo:         refundNo,
		PlatformRefundId: l.createNullString(platformRefundId),
		OrderId:          order.Id,
		UserId:           order.UserId,
		ProductId:        order.ProductId,
		RefundAmount:     req.RefundAmount,
		RefundReason:     l.createNullString(req.RefundReason),
		Status:           refundStatus,
		RefundTime:       sql.NullTime{Time: time.Now(), Valid: true},
	}

	_, err := l.svcCtx.OrderRefundModel.Insert(l.ctx, nil, refund)
	if err != nil {
		return fmt.Errorf("创建退款记录失败: %v", err)
	}
	return nil
}

// generateRefundNo 生成退款单号
func (l *AdminRefundOrderLogic) generateRefundNo(orderNo string) string {
	return fmt.Sprintf("%s%s", RefundNoPrefix, orderNo)
}

// createNullString 创建 sql.NullString
func (l *AdminRefundOrderLogic) createNullString(value string) sql.NullString {
	return sql.NullString{
		String: value,
		Valid:  value != "",
	}
}
