package pay

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"jnc-server/app/main/api/internal/svc"
	"jnc-server/app/main/api/internal/types"
	"jnc-server/app/main/model"
	"jnc-server/common/ctxdata"
	"jnc-server/common/xerr"
	"os"
	"strings"
	"time"

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

type PaymentLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}
type PaymentTypeResp struct {
	amount      float64
	outTradeNo  string
	description string
	orderID     string // 订单ID，用于开发环境测试支付模式
}

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

func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) {
	var paymentTypeResp *PaymentTypeResp
	var prepayData interface{}
	var orderID string

	// 检查是否为开发环境的测试支付模式
	env := os.Getenv("ENV")
	isDevTestPayment := env == "development" && (req.PayMethod == "test" || req.PayMethod == "test_empty")
	isEmptyReportMode := env == "development" && req.PayMethod == "test_empty"

	l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		switch req.PayType {
		case "agent_vip":
			// 系统简化：已废弃会员充值功能
			return errors.Wrapf(xerr.NewErrMsg("该功能已废弃"), "")

		case "query":
			paymentTypeResp, err = l.QueryOrderPayment(req, session)
			if err != nil {
				return err
			}

		case "agent_upgrade":
			// 系统简化：已废弃升级功能
			return errors.Wrapf(xerr.NewErrMsg("该功能已废弃"), "")
		}

		// 开发环境测试支付模式：跳过实际支付流程
		// 注意：订单状态更新在事务外进行，避免在事务中查询不到订单的问题
		if isDevTestPayment {
			// 获取订单ID（从 QueryOrderPayment 返回的 orderID）
			if paymentTypeResp.orderID == "" {
				return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "开发测试模式，订单ID无效")
			}
			orderID = paymentTypeResp.orderID

			// 在事务中只记录订单ID，不更新订单状态
			// 订单状态的更新和后续流程在事务提交后处理
			logx.Infof("开发环境测试支付模式：订单 %s (ID: %s) 将在事务提交后更新状态", paymentTypeResp.outTradeNo, orderID)

			// 返回测试支付标识
			prepayData = "test_payment_success"
			return nil
		}

		// 正常支付流程
		var createOrderErr error
		if req.PayMethod == "wechat" {
			prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
		} else if req.PayMethod == "alipay" {
			prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
		} else if req.PayMethod == "easypay_alipay" {
			if l.svcCtx.EasyPayService == nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "易支付服务未启用")
			}
			prepayData, createOrderErr = l.svcCtx.EasyPayService.CreateEasyPayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
		} else if req.PayMethod == "appleiap" {
			prepayData = l.svcCtx.ApplePayService.GetIappayAppID(paymentTypeResp.outTradeNo)
		}
		if createOrderErr != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	// 开发环境测试支付模式：事务提交后处理订单状态更新和后续流程
	if isDevTestPayment && paymentTypeResp != nil && paymentTypeResp.orderID != "" {
		// 使用 goroutine 异步处理，确保事务已完全提交
		go func() {
			// 短暂延迟，确保事务已完全提交到数据库
			time.Sleep(200 * time.Millisecond)

			finalOrderID := paymentTypeResp.orderID

			// 查找订单并更新状态为已支付
			order, findOrderErr := l.svcCtx.OrderModel.FindOne(context.Background(), finalOrderID)
			if findOrderErr != nil {
				logx.Errorf("开发测试模式，查找订单失败，订单ID: %s, 错误: %v", finalOrderID, findOrderErr)
				return
			}

			// 更新订单状态为已支付
			order.Status = "paid"
			now := time.Now()
			order.PayTime = sql.NullTime{Time: now, Valid: true}

			// 空报告模式：在 PaymentPlatform 字段中标记，用于后续生成空报告
			if isEmptyReportMode {
				order.PaymentPlatform = "test_empty"
				logx.Infof("开发环境空报告模式：订单 %s (ID: %s) 已标记为空报告模式", paymentTypeResp.outTradeNo, finalOrderID)
			}

			// 更新订单状态（在事务外执行）
			updateErr := l.svcCtx.OrderModel.UpdateWithVersion(context.Background(), nil, order)
			if updateErr != nil {
				logx.Errorf("开发测试模式，更新订单状态失败，订单ID: %s, 错误: %+v", finalOrderID, updateErr)
				return
			}

			logx.Infof("开发环境测试支付模式：订单 %s (ID: %s) 已自动标记为已支付", paymentTypeResp.outTradeNo, finalOrderID)

			// 再次短暂延迟，确保订单状态更新已提交
			time.Sleep(100 * time.Millisecond)

			// 根据订单类型处理后续流程
			if strings.HasPrefix(paymentTypeResp.outTradeNo, "U_") {
				// 系统简化：升级订单已废弃，跳过处理
				logx.Infof("开发测试模式，升级订单已废弃，订单号: %s", paymentTypeResp.outTradeNo)
			} else {
				// 查询订单：发送支付成功通知任务，触发后续流程（生成报告和代理处理）
				if sendErr := l.svcCtx.AsynqService.SendQueryTask(finalOrderID); sendErr != nil {
					logx.Errorf("开发测试模式，发送支付成功通知任务失败，订单ID: %s, 错误: %+v", finalOrderID, sendErr)
				} else {
					logx.Infof("开发测试模式，已发送支付成功通知任务，订单ID: %s", finalOrderID)
				}
			}
		}()
	}

	switch v := prepayData.(type) {
	case string:
		// 如果 prepayData 是字符串类型，直接返回
		return &types.PaymentResp{PrepayId: v, OrderNo: paymentTypeResp.outTradeNo}, nil
	default:
		return &types.PaymentResp{PrepayData: prepayData, OrderNo: paymentTypeResp.outTradeNo}, nil
	}
}

func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
	userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
	if getUidErr != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
	}
	outTradeNo := req.Id
	redisKey := fmt.Sprintf(types.QueryCacheKey, userID, outTradeNo)
	cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
	if cacheErr != nil {
		if cacheErr == redis.Nil {
			return nil, errors.Wrapf(xerr.NewErrMsg("订单已过期"), "生成订单, 缓存不存在, %+v", cacheErr)
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取缓存失败, %+v", cacheErr)
	}
	var data types.QueryCacheLoad
	err = json.Unmarshal([]byte(cache), &data)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %v", err)
	}

	product, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, data.Product)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %v", err)
	}

	var amount float64
	user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
	}

	var agentLinkModel *model.AgentLink
	if data.AgentIdentifier != "" {
		var findAgentLinkErr error
		agentLinkModel, findAgentLinkErr = l.svcCtx.AgentLinkModel.FindOneByLinkIdentifier(l.ctx, data.AgentIdentifier)
		if findAgentLinkErr != nil {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取代理链接失败: %+v", findAgentLinkErr)
		}
		amount = agentLinkModel.SetPrice
	} else {
		amount = product.SellPrice
	}

	if user.Inside == 1 {
		amount = 0.01
	}
	order := model.Order{
		Id:              uuid.NewString(),
		OrderNo:         outTradeNo,
		UserId:          userID,
		ProductId:       product.Id,
		PaymentPlatform: req.PayMethod,
		PaymentScene:    "app",
		Amount:          amount,
		Status:          "pending",
	}
	_, insertOrderErr := l.svcCtx.OrderModel.Insert(l.ctx, session, &order)
	if insertOrderErr != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
	}
	orderID := order.Id

	// 如果是代理推广订单，创建完整的代理订单记录
	if data.AgentIdentifier != "" && agentLinkModel != nil {
		// 获取产品配置（必须存在）
		productConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, product.Id)
		if err != nil {
			if errors.Is(err, model.ErrNotFound) {
				return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单失败，产品配置不存在, productId: %s，请先在后台配置产品价格参数", product.Id)
			}
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 查询产品配置失败: %+v", err)
		}

		// 系统简化：移除等级加成，直接使用底价
		actualBasePrice := productConfig.BasePrice

		// 计算提价成本（使用产品配置）
		priceThreshold := 0.0
		priceFeeRate := 0.0
		if productConfig.PriceThreshold.Valid {
			priceThreshold = productConfig.PriceThreshold.Float64
		}
		if productConfig.PriceFeeRate.Valid {
			priceFeeRate = productConfig.PriceFeeRate.Float64
		}

		priceCost := 0.0
		if agentLinkModel.SetPrice > priceThreshold {
			priceCost = (agentLinkModel.SetPrice - priceThreshold) * priceFeeRate
		}

		// 计算代理收益
		agentProfit := agentLinkModel.SetPrice - actualBasePrice - priceCost

		// 创建代理订单记录
		agentOrder := model.AgentOrder{
			Id:              uuid.NewString(),
			AgentId:         agentLinkModel.AgentId,
			OrderId:         orderID,
			ProductId:       product.Id,
			OrderAmount:     amount,
			SetPrice:        agentLinkModel.SetPrice,
			ActualBasePrice: actualBasePrice,
			PriceCost:       priceCost,
			AgentProfit:     agentProfit,
			ProcessStatus:   0, // 待处理
		}
		_, agentOrderInsert := l.svcCtx.AgentOrderModel.Insert(l.ctx, session, &agentOrder)
		if agentOrderInsert != nil {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
		}
	}
	return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName, orderID: orderID}, nil
}
