package admin_agent

import (
	"context"
	"database/sql"
	"fmt"
	"time"
	"qnc-server/common/globalkey"
	"qnc-server/common/xerr"
	"qnc-server/pkg/lzkit/lzUtils"

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

	"qnc-server/app/main/api/internal/svc"
	"qnc-server/app/main/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

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

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

func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWithdrawalReq) (resp *types.AdminAuditWithdrawalResp, err error) {
	// 1. 查询提现记录
	withdrawal, err := l.svcCtx.AgentWithdrawalModel.FindOne(l.ctx, req.WithdrawalId)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询提现记录失败, %v", err)
	}

	// 3. 检查状态（必须是待审核状态）
	if withdrawal.Status != 1 {
		return nil, errors.Wrapf(xerr.NewErrMsg("该提现记录已处理"), "")
	}

	// 4. 使用事务处理审核
	err = l.svcCtx.AgentWithdrawalModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
		if req.Status == 2 { // 审核通过
			// 4.1 更新提现记录状态为提现中
			withdrawal.Status = 4 // 提现中
			withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true}
			if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
				return errors.Wrapf(err, "更新提现记录失败")
			}

			// 4.2 调用支付宝转账接口
			outBizNo := withdrawal.WithdrawNo
			transferResp, err := l.svcCtx.AlipayService.AliTransfer(transCtx, withdrawal.PayeeAccount, withdrawal.PayeeName, withdrawal.ActualAmount, "代理提现", outBizNo)
			if err != nil {
				// 转账失败，更新状态为失败
				withdrawal.Status = 6 // 提现失败
				withdrawal.Remark = sql.NullString{String: fmt.Sprintf("转账失败: %v", err), Valid: true}
				l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal)

				// 解冻余额
				wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId)
				if err == nil {
					wallet.FrozenBalance -= withdrawal.Amount
					wallet.Balance += withdrawal.Amount
					l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet)
				}

				return errors.Wrapf(err, "支付宝转账失败")
			}

			// 4.3 根据转账结果更新状态
			switch transferResp.Status {
			case "SUCCESS":
				// 转账成功
				withdrawal.Status = 5 // 提现成功
				if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
					return errors.Wrapf(err, "更新提现记录失败")
				}

				// 更新钱包（解冻并扣除）
				wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId)
				if err != nil {
					return errors.Wrapf(err, "查询钱包失败")
				}
				wallet.FrozenBalance -= withdrawal.Amount
				wallet.WithdrawnAmount += withdrawal.Amount
				if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil {
					return errors.Wrapf(err, "更新钱包失败")
				}

				// 更新扣税记录状态
				taxBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().
					Where("withdrawal_id = ? AND del_state = ?", withdrawal.Id, globalkey.DelStateNo)
				taxRecords, err := l.svcCtx.AgentWithdrawalTaxModel.FindAll(transCtx, taxBuilder, "")
				if err == nil && len(taxRecords) > 0 {
					taxRecord := taxRecords[0]
					taxRecord.TaxStatus = 2 // 已扣税
					taxRecord.TaxTime = lzUtils.TimeToNullTime(time.Now())
					l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(transCtx, session, taxRecord)
				}

			case "FAIL":
				// 转账失败
				withdrawal.Status = 6 // 提现失败
				errorMsg := l.mapAlipayError(transferResp.SubCode)
				withdrawal.Remark = sql.NullString{String: errorMsg, Valid: true}
				if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
					return errors.Wrapf(err, "更新提现记录失败")
				}

				// 解冻余额
				wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId)
				if err == nil {
					wallet.FrozenBalance -= withdrawal.Amount
					wallet.Balance += withdrawal.Amount
					l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet)
				}

			case "DEALING":
				// 处理中，保持提现中状态，后续通过轮询更新
				// 状态已经是4（提现中），无需更新
			}

		} else if req.Status == 3 { // 审核拒绝
			// 4.1 更新提现记录状态为拒绝
			withdrawal.Status = 3 // 审核拒绝
			withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true}
			if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
				return errors.Wrapf(err, "更新提现记录失败")
			}

			// 4.2 解冻余额
			wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId)
			if err != nil {
				return errors.Wrapf(err, "查询钱包失败")
			}
			wallet.FrozenBalance -= withdrawal.Amount
			wallet.Balance += withdrawal.Amount
			if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil {
				return errors.Wrapf(err, "更新钱包失败")
			}
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return &types.AdminAuditWithdrawalResp{
		Success: true,
	}, nil
}

// mapAlipayError 映射支付宝错误码
func (l *AdminAuditWithdrawalLogic) mapAlipayError(code string) string {
	errorMapping := map[string]string{
		"PAYEE_USERINFO_ERROR":     "收款方姓名或信息不匹配",
		"PAYEE_CARD_INFO_ERROR":    "收款支付宝账号及户名不一致",
		"PAYEE_IDENTITY_NOT_MATCH": "收款方身份信息不匹配",
		"PAYEE_USER_IS_INST":       "收款方为金融机构，不能使用提现功能",
		"PAYEE_USER_TYPE_ERROR":    "该支付宝账号类型不支持提现",
	}
	if msg, ok := errorMapping[code]; ok {
		return msg
	}
	return "系统错误，请联系客服"
}
