package holders

import (
	"fmt"
	"log"
	"time"

	"github.com/gothinkster/golang-gin-realworld-example-app/common"
)

// Asset represents a product/asset in the database
type Asset struct {
	ID              int64   `gorm:"column:id"`
	AssetCode       string  `gorm:"column:asset_code"`
	Name            string  `gorm:"column:name"`
	TokenRole       string  `gorm:"column:token_role"`
	ChainID         int     `gorm:"column:chain_id"`
	ContractAddress string  `gorm:"column:contract_address"`
	DeployBlock     *uint64 `gorm:"column:deploy_block"`
}


const zeroAddress = "0x0000000000000000000000000000000000000000"

// LoadConfigFromDB loads contract addresses and deploy blocks from database based on chain ID
func LoadConfigFromDB(chainID int64) (Config, error) {
	db := common.GetDB()

	log.Printf("📚 [Scanner] 从数据库加载配置 - Chain ID: %d", chainID)

	switch chainID {
	case 97, 421614:
		// supported
	default:
		return Config{}, fmt.Errorf("unsupported chain ID: %d", chainID)
	}

	// Load YT assets by token_role filtered by chain_id
	var assets []Asset
	if err := db.Table("assets").
		Where("token_role = ? AND chain_id = ? AND is_active = ?", "yt_token", chainID, true).
		Find(&assets).Error; err != nil {
		return Config{}, fmt.Errorf("failed to load assets: %w", err)
	}

	ytVaults := make([]VaultConfig, 0, len(assets))
	for _, asset := range assets {
		if asset.ContractAddress == "" || asset.ContractAddress == zeroAddress {
			log.Printf("⚠️  [Scanner] 跳过 %s (地址未配置)", asset.AssetCode)
			continue
		}
		if asset.DeployBlock == nil || *asset.DeployBlock == 0 {
			log.Printf("⚠️  [Scanner] 跳过 %s (deploy_block 未配置)", asset.AssetCode)
			continue
		}

		ytVaults = append(ytVaults, VaultConfig{
			Name:        asset.AssetCode,
			Address:     asset.ContractAddress,
			DeployBlock: *asset.DeployBlock,
		})
		log.Printf("   ✓ %s: %s (部署区块: %d)", asset.AssetCode, asset.ContractAddress, *asset.DeployBlock)
	}
	log.Printf("✅ [Scanner] 加载了 %d 个 YT Vault", len(ytVaults))

	// Load YTLPToken address from system_contracts
	var ytLPContract struct {
		Address     string  `gorm:"column:address"`
		DeployBlock *uint64 `gorm:"column:deploy_block"`
	}
	ytLPAddress := ""
	var ytLPDeployBlock uint64
	err := db.Table("system_contracts").
		Where("name = ? AND chain_id = ? AND is_active = ?", "YTLPToken", chainID, 1).
		Select("address, deploy_block").
		First(&ytLPContract).Error
	if err != nil {
		log.Printf("⚠️  [Scanner] 未找到 YTLPToken 配置")
	} else if ytLPContract.Address == "" || ytLPContract.Address == zeroAddress {
		log.Printf("⚠️  [Scanner] 跳过 ytLP (地址未配置)")
	} else if ytLPContract.DeployBlock == nil || *ytLPContract.DeployBlock == 0 {
		log.Printf("⚠️  [Scanner] 跳过 ytLP (deploy_block 未配置)")
	} else {
		ytLPAddress = ytLPContract.Address
		ytLPDeployBlock = *ytLPContract.DeployBlock
		log.Printf("✅ [Scanner] ytLP: %s (部署区块: %d)", ytLPAddress, ytLPDeployBlock)
	}

	rpcURL := getRPCURLForChain(chainID)

	config := Config{
		ChainID:     int(chainID),
		RPCURL:      rpcURL,
		YTVaults:    ytVaults,
		YTLPAddress: ytLPAddress,
		DeploymentBlocks: DeploymentBlocks{
			YTLP: ytLPDeployBlock,
		},
		PollInterval: 30 * time.Second,
		BatchSize:    9999,
	}

	log.Printf("📊 [Scanner] 配置加载完成: YT Vaults=%d, ytLP=%s, RPC=%s",
		len(config.YTVaults), config.YTLPAddress, config.RPCURL)

	return config, nil
}

// getRPCURLForChain returns the RPC URL for the given chain ID
func getRPCURLForChain(chainID int64) string {
	switch chainID {
	case 421614:
		return "https://api.zan.top/node/v1/arb/sepolia/baf84c429d284bb5b676cb8c9ca21c07"
	case 97:
		return "https://api.zan.top/node/v1/bsc/testnet/baf84c429d284bb5b676cb8c9ca21c07"
	default:
		return ""
	}
}

// TableName sets the table name for GORM
func (Asset) TableName() string {
	return "assets"
}

