// Package models 定义钱包相关的数据模型和数据库操作
package models

import (
	"errors"

	"bsm/full/module/finance/wallet/internal/impl"
	"git.apinb.com/bsm-sdk/core/types"
	"git.apinb.com/bsm-sdk/core/utils"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"gorm.io/gorm"
)

// InitData 初始化默认钱包数据
func InitData() error {
	var (
		cnt          int64
		err          error
		userIdentity string
	)

	// 获取默认用户唯一标识
	err = impl.DBService.Table("passport_account").Select("identity").Where("account=?", "demo").Find(&userIdentity).Error
	if err != nil {
		return err
	}
	if userIdentity == "" {
		return errors.New("默认用户未找到")
	}

	// 检查是否已经创建了钱包信息
	err = impl.DBService.Model(&WalletBasic{}).Where("passport_identity=?", userIdentity).Count(&cnt).Error
	if err != nil {
		return err
	}

	// 如果钱包不存在，则创建默认钱包
	if cnt == 0 {
		pa := WalletBasic{
			Balance:           0,
			WithdrawalBalance: 0,
			Std_Identity:      types.Std_Identity{Identity: utils.ULID()},
			Std_Passport:      types.Std_Passport{PassportIdentity: userIdentity},
		}
		err = impl.DBService.Create(&pa).Error
		if err != nil {
			return err
		}
	}

	return nil
}

// GetWalletBalanceByPassportIdentity 根据用户身份获取钱包余额
func GetWalletBalanceByPassportIdentity(passport_identity string) float64 {
	wallet := new(WalletBasic)
	err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
	if err != nil {
		return 0.00
	}
	return float64(wallet.Balance / 100)
}

// WalletExists 检查钱包是否存在
func WalletExists(passportIdentity string) *WalletBasic {
	wallet := new(WalletBasic)
	err := impl.DBService.Where("passport_identity = ?", passportIdentity).First(wallet).Error
	if err != nil {
		return nil
	}
	return wallet
}

// GetWalletByPassportIdentity 根据用户身份获取钱包，如果不存在则创建
func GetWalletByPassportIdentity(passport_id uint, passport_identity string) (*WalletBasic, error) {
	wallet := new(WalletBasic)
	err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 钱包不存在，创建新钱包
			wallet.Identity = utils.UUID()
			wallet.PassportID = passport_id
			wallet.PassportIdentity = passport_identity
			impl.DBService.Create(wallet)
			return wallet, nil
		} else {
			return nil, err
		}
	}
	return wallet, nil
}

// GetWalletByPassportIdentityT 根据用户身份获取钱包（不创建）
func GetWalletByPassportIdentityT(passport_id int64, passport_identity string) (*WalletBasic, error) {
	wallet := &WalletBasic{}
	err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
	return wallet, err
}

// GetTransPriceByOrderNo 根据订单号获取交易价格
func GetTransPriceByOrderNo(no string) (int64, error) {
	var amount int64
	impl.DBService.Select("trans_price").Table("order_summary").Where("order_no=? and status=1", no).Scan(&amount)
	if amount == 0 {
		return 0, status.Error(codes.Internal, "Order is close.")
	}
	return amount, nil
}

// GetWalletPaymentByIdentity 根据身份和支付ID获取钱包支付记录
func GetWalletPaymentByIdentity(passport_identity, identity string) (*WalletPayment, error) {
	fp := new(WalletPayment)
	err := impl.DBService.Where("passport_identity=? and identity=?", passport_identity, identity).First(&fp).Error
	return fp, err
}

// UpsetWalletPaymentByIdentity 更新钱包支付记录状态
func UpsetWalletPaymentByIdentity(passport_identity, identity string, CallbackStatus int8, CallbackMsg string) error {
	err := impl.DBService.Model(&WalletPayment{}).Where("passport_identity=? and identity=?", passport_identity, identity).Updates(map[string]interface{}{"status": CallbackStatus, "call_back_msg": CallbackMsg}).Error
	return err
}

// CreatePaymentRecord 创建支付记录
func CreatePaymentRecord(fp *WalletPayment) error {
	return impl.DBService.Create(&fp).Error
}

// CreateTradeRecord 创建交易记录
func CreateTradeRecord(fr *WalletRecord) error {
	return impl.DBService.Create(&fr).Error
}

// ChargeWallet 为钱包充值
func ChargeWallet(passport_id uint, passport_identity, order_no string, paySource int32, amount int64) error {
	wallet, err := GetWalletByPassportIdentity(passport_id, passport_identity)
	if err != nil {
		return err
	}

	// 更新钱包余额
	data := map[string]interface{}{
		"balance":            wallet.Balance + amount,
		"withdrawal_balance": wallet.WithdrawalBalance + amount,
	}
	err = impl.DBService.Model(&WalletBasic{}).Where("identity=?", wallet.Identity).UpdateColumns(data).Error
	if err != nil {
		return err
	} else {
		// 创建交易记录
		record := &WalletRecord{
			WalletIdentity: wallet.Identity,
			TransType:      1, // 充值类型
			InTradeNo:      order_no,
			Money:          amount,
			TradeType:      1, // 收入类型
			PayChannel:     int8(paySource),
		}
		record.PassportID = passport_id
		record.PassportIdentity = passport_identity
		CreateTradeRecord(record)
	}

	return nil
}

// FindWalletRecords 查询钱包交易记录
func FindWalletRecords(passportIdentity, start, end string, transType, tradeType, page, pageSize int64) ([]*WalletRecord, int64, error) {
	list := make([]*WalletRecord, 0)
	tx := impl.DBService.Where("passport_identity = ?", passportIdentity)

	// 添加时间范围过滤
	if start != "" {
		tx.Where("created_at >= ?", start)
	}
	if end != "" {
		tx.Where("created_at <= ?", end)
	}

	// 添加交易类型过滤
	if transType != 0 {
		tx.Where("trans_type = ?", transType)
	}
	if tradeType != 0 {
		tx.Where("trade_type = ?", tradeType)
	}

	// 分页查询
	res := tx.Order("created_at desc").Limit(int(pageSize)).Offset(int((page - 1) * pageSize)).Find(&list)
	if res.Error != nil {
		if !errors.Is(res.Error, gorm.ErrRecordNotFound) {
			return nil, 0, res.Error
		}
		return nil, 0, nil
	}
	return list, res.RowsAffected, nil
}
