package agent

import (
	"context"
	"database/sql"
	"regexp"
	"time"
	"tydata-server/app/main/model"
	"tydata-server/common/ctxdata"
	"tydata-server/common/xerr"

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

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

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

// 提现类型常量
const (
	WithdrawTypeAlipay   = 1 // 支付宝提现
	WithdrawTypeBankCard = 2 // 银行卡提现
)

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

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

func (l *BankCardWithdrawalLogic) BankCardWithdrawal(req *types.BankCardWithdrawalReq) (resp *types.WithdrawalResp, err error) {
	var (
		outBizNo    string
		withdrawRes = &types.WithdrawalResp{}
		agentID     int64
	)
	var finalWithdrawAmount float64 // 实际到账金额

	// 验证银行卡号格式（16-19位数字）
	bankCardNoRegex := regexp.MustCompile(`^\d{16,19}$`)
	if !bankCardNoRegex.MatchString(req.BankCardNo) {
		return nil, errors.Wrapf(xerr.NewErrMsg("银行卡号格式不正确，请输入16-19位数字"), "银行卡号格式验证失败")
	}

	// 验证开户支行不能为空
	if req.BankName == "" {
		return nil, errors.Wrapf(xerr.NewErrMsg("开户支行不能为空"), "开户支行验证失败")
	}

	// 使用事务处理核心操作
	err = l.svcCtx.AgentModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		userID, err := ctxdata.GetUidFromCtx(l.ctx)
		if err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
		}

		// 查询代理信息
		agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
		if err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
		}
		agentID = agentModel.Id // 保存agentId用于日志

		// 查询实名认证信息
		agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agentModel.Id)
		if err != nil {
			if errors.Is(err, model.ErrNotFound) {
				return errors.Wrapf(xerr.NewErrMsg("您未进行实名认证, 无法提现"), "您未进行实名认证")
			}
			return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询代理实名信息失败: %v", err)
		}
		if agentRealName.Status != model.AgentRealNameStatusApproved {
			return errors.Wrapf(xerr.NewErrMsg("您的实名认证未通过, 无法提现"), "您的实名认证未通过")
		}

		// 查询钱包
		agentWallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
		if err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理钱包失败: %v", err)
		}

		// 校验可提现金额
		if req.Amount > agentWallet.Balance {
			return errors.Wrapf(xerr.NewErrMsg("您可提现的余额不足"), "余额不足")
		}

		// 最低提现金额验证
		if req.Amount < 50 {
			return errors.Wrapf(xerr.NewErrMsg("提现金额不能低于50元"), "金额验证失败")
		}

		// 生成交易号
		outBizNo = "BC_" + l.svcCtx.AlipayService.GenerateOutTradeNo()

		// 冻结资金（事务内操作）
		if err = l.freezeFunds(session, agentWallet, req.Amount); err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "资金冻结失败: %v", err)
		}

		yearMonth := int64(time.Now().Year()*100 + int(time.Now().Month()))
		// 统一按6%收取税收
		taxRate := l.svcCtx.Config.TaxConfig.TaxRate
		var (
			taxAmount        float64 // 应缴税费
			taxDeductionPart float64 // 应税金额
			TaxStatus        int64   // 扣税状态
			exemptionAmount  float64 // 免税金额（固定为0）
		)

		// 统一扣税逻辑：所有提现都按6%收取税收
		exemptionAmount = 0                          // 免税金额 = 0
		TaxStatus = model.TaxStatusPending           // 扣税状态 = 待扣税
		taxDeductionPart = req.Amount                // 应税金额 = 提现金额
		taxAmount = taxDeductionPart * taxRate       // 应缴税费 = 应税金额 * 税率
		finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费

		// 创建提现记录（初始状态为申请中，提现类型为银行卡）
		withdrawalID, err := l.createBankCardWithdrawalRecord(session, agentModel.Id, req.BankCardNo, req.BankName, agentRealName.Name, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
		if err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建提现记录失败: %v", err)
		}

		// 扣税记录
		taxModel := &model.AgentWithdrawalTax{
			AgentId:           agentModel.Id,
			YearMonth:         yearMonth,
			WithdrawalId:      withdrawalID,
			WithdrawalAmount:  req.Amount,
			ExemptionAmount:   exemptionAmount,
			TaxableAmount:     taxDeductionPart,
			TaxRate:           taxRate,
			TaxAmount:         taxAmount,
			ActualAmount:      finalWithdrawAmount,
			TaxStatus:         TaxStatus,
			Remark:            sql.NullString{String: "银行卡提现申请，待审核扣税", Valid: true},
			ExemptionRecordId: 0, // 不再使用免税额度记录
		}
		_, err = l.svcCtx.AgentWithdrawalTaxModel.Insert(ctx, session, taxModel)
		if err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建扣税记录失败: %v", err)
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	// 银行卡提现不需要调用支付接口，直接返回申请中状态
	withdrawRes.Status = WithdrawStatusProcessing
	withdrawRes.FailMsg = ""

	l.Logger.Infof("银行卡提现申请成功 outBizNo:%s agentId:%d amount:%f", outBizNo, agentID, req.Amount)
	return withdrawRes, nil
}

// 创建银行卡提现记录（事务内操作）
func (l *BankCardWithdrawalLogic) createBankCardWithdrawalRecord(session sqlx.Session, agentID int64, bankCardNo string, bankName string, payeeName string, amount float64, finalWithdrawAmount float64, taxAmount float64, outBizNo string) (int64, error) {
	record := &model.AgentWithdrawal{
		AgentId:      agentID,
		WithdrawType: WithdrawTypeBankCard, // 银行卡提现
		WithdrawNo:   outBizNo,
		PayeeAccount: bankCardNo, // 银行卡号存储在PayeeAccount字段
		Amount:       amount,
		ActualAmount: finalWithdrawAmount,
		TaxAmount:    taxAmount,
		Status:       StatusProcessing, // 申请中状态
		BankCardNo:   sql.NullString{String: bankCardNo, Valid: true},
		BankName:     sql.NullString{String: bankName, Valid: true},
		PayeeName:    sql.NullString{String: payeeName, Valid: true},
	}

	result, err := l.svcCtx.AgentWithdrawalModel.Insert(l.ctx, session, record)
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// 冻结资金（事务内操作）
func (l *BankCardWithdrawalLogic) freezeFunds(session sqlx.Session, wallet *model.AgentWallet, amount float64) error {
	// 记录变动前的余额
	balanceBefore := wallet.Balance
	frozenBalanceBefore := wallet.FrozenBalance

	// 更新钱包余额
	wallet.Balance -= amount
	wallet.FrozenBalance += amount
	err := l.svcCtx.AgentWalletModel.UpdateWithVersion(l.ctx, session, wallet)
	if err != nil {
		return err
	}

	// 记录交易流水（冻结操作）
	err = l.svcCtx.AgentService.CreateWalletTransaction(
		l.ctx,
		session,
		wallet.AgentId,
		model.WalletTransactionTypeFreeze,
		amount,               // 变动金额
		balanceBefore,        // 变动前余额
		wallet.Balance,       // 变动后余额
		frozenBalanceBefore,  // 变动前冻结余额
		wallet.FrozenBalance, // 变动后冻结余额
		"",                   // 关联交易ID（暂时为空，创建提现记录后可以更新）
		0,                    // 关联用户ID
		"提现申请冻结资金",           // 备注
	)
	if err != nil {
		return err
	}

	return nil
}
