package admin_order

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

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

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

const (
	PaymentPlatformAlipay              = "alipay"
	PaymentPlatformWechat              = "wechat"
	PaymentPlatformEasyPay             = "easypay_alipay"
	PaymentPlatformYunYinSignPay       = "yunyinSignPay"
	PaymentPlatformYunYinSignPayWechat = "yunyinSignPay_wechat"
	PaymentPlatformYunYinSignPayAlipay = "yunyinSignPay_alipay"
	OrderStatusPaid                    = "paid"
	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 PaymentPlatformAlipay:
		return l.handleAlipayRefund(order, req)
	case PaymentPlatformWechat:
		return l.handleWechatRefund(order, req)
	case PaymentPlatformEasyPay:
		return l.handleEasyPayRefund(order, req)
	case PaymentPlatformYunYinSignPay, PaymentPlatformYunYinSignPayWechat, PaymentPlatformYunYinSignPayAlipay:
		return l.handleYunYinSignPayRefund(order, req)
	default:
		return nil, errors.Wrapf(xerr.NewErrMsg("不支持的支付平台"), "AdminRefundOrder, 不支持的支付平台: %s", order.PaymentPlatform)
	}
}

// getAndValidateOrder 获取并验证订单信息
func (l *AdminRefundOrderLogic) getAndValidateOrder(orderId string, 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 != 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)
		}
		logx.Infof("支付宝退款失败: %v", refundResp)
		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
}

// handleEasyPayRefund 处理易支付退款
func (l *AdminRefundOrderLogic) handleEasyPayRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
	// 检查易支付服务是否启用
	if l.svcCtx.EasyPayService == nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 易支付服务未启用")
	}

	// 调用易支付退款接口
	err := l.svcCtx.EasyPayService.Refund(l.ctx, order.OrderNo, req.RefundAmount)
	if err != nil {
		// 易支付退款失败，创建失败记录但不更新订单状态
		refundNo := l.generateRefundNo(order.OrderNo)
		createErr := l.createRefundRecordOnly(order, req, refundNo, "", model.OrderRefundStatusFailed)
		if createErr != nil {
			logx.Errorf("创建易支付退款失败记录时出错: %v", createErr)
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 易支付退款失败 err: %v", err)
	}

	// 易支付退款成功，创建成功记录
	refundNo := l.generateRefundNo(order.OrderNo)
	// 易支付退款是同步的，直接标记为成功
	err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", model.OrderStatusRefunded, model.OrderRefundStatusSuccess)
	if err != nil {
		return nil, err
	}

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

// handleYunYinSignPayRefund 处理云印签支付退款
func (l *AdminRefundOrderLogic) handleYunYinSignPayRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
	// 检查云印签支付服务是否启用
	if l.svcCtx.YunYinSignPayService == nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 云印签支付服务未启用")
	}

	// 查询云印签订单获取参与方ID（如果存在）
	var participateId int64
	yunyinOrder, err := l.svcCtx.YunyinSignPayOrderModel.FindOneByOrderId(l.ctx, order.Id)
	if err != nil {
		// 如果查询不到云印签订单记录，可能是历史订单或数据不一致，使用订单号退款
		if errors.Is(err, model.ErrNotFound) {
			logx.Infof("未找到云印签订单记录，将使用订单号退款，订单ID: %s, 订单号: %s", order.Id, order.OrderNo)
			participateId = 0 // 使用订单号退款
		} else {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询云印签订单失败, 订单ID: %s, 错误: %v", order.Id, err)
		}
	} else {
		// 获取参与方ID（ParticipantId 是 string 类型，需要转换为 int64）
		if yunyinOrder.ParticipantId != "" {
			// 尝试将字符串转换为int64
			if _, parseErr := fmt.Sscanf(yunyinOrder.ParticipantId, "%d", &participateId); parseErr != nil {
				logx.Errorf("解析参与方ID失败，订单ID: %s, ParticipantId: %s, 错误: %v", order.Id, yunyinOrder.ParticipantId, parseErr)
				// 如果解析失败，participateId 保持为 0，使用订单号退款
			} else {
				logx.Infof("成功解析参与方ID，订单ID: %s, ParticipantId: %s, participateId: %d", order.Id, yunyinOrder.ParticipantId, participateId)
			}
		}
	}

	// 调用云印签退款接口
	refundErr := l.svcCtx.YunYinSignPayService.RefundPayeeBill(
		l.ctx,
		order.OrderNo,
		participateId,
		req.RefundAmount,
		req.RefundReason,
	)
	if refundErr != nil {
		// 云印签退款失败，创建失败记录但不更新订单状态
		refundNo := l.generateRefundNo(order.OrderNo)
		createErr := l.createRefundRecordOnly(order, req, refundNo, "", model.OrderRefundStatusFailed)
		if createErr != nil {
			logx.Errorf("创建云印签退款失败记录时出错: %v", createErr)
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 云印签退款失败 err: %v", refundErr)
	}

	// 云印签退款成功，创建成功记录
	refundNo := l.generateRefundNo(order.OrderNo)
	// 检查是否全额退款
	isFullRefund := req.RefundAmount >= order.Amount-0.01 // 允许1分钱的误差

	var orderStatus string
	if isFullRefund {
		orderStatus = model.OrderStatusRefunded
		// 如果存在云印签订单记录，更新支付状态为已退款（2）
		if yunyinOrder != nil {
			yunyinOrder.PayStatus = 2
			if _, updateErr := l.svcCtx.YunyinSignPayOrderModel.Update(l.ctx, nil, yunyinOrder); updateErr != nil {
				logx.Errorf("更新云印签订单状态失败: %v", updateErr)
			}
		}
	} else {
		// 部分退款保持已支付状态
		orderStatus = model.OrderStatusPaid
	}

	// 云印签退款是异步的，但API返回成功表示申请已提交，标记为成功
	err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", orderStatus, model.OrderRefundStatusSuccess)
	if err != nil {
		return nil, err
	}

	return &types.AdminRefundOrderResp{
		Status:   orderStatus,
		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{
			Id:               uuid.NewString(),
			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{
		Id:               uuid.NewString(),
		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 != "",
	}
}
