//! DD 统一共享类型库
//!
//! 为去中心化决策生态系统提供统一的类型定义、接口和工具函数
//! 合并了原有的 decentralized_decision_types 和 shared-interfaces 功能

use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Binary, StdError, Timestamp, Uint128};
use cw_storage_plus::{Key, KeyDeserialize, PrimaryKey};

// ==================== 核心类型定义 ====================

#[cw_serde]
/// 去中心化决策算法类型
pub enum DDAlgorithmType {
    /// 单目标抽奖决策
    SingleTargetLottery,
    /// 多目标抽奖决策
    MultiTargetLottery,
    /// 多等级抽奖决策
    MultiLevelLottery,
    /// 多目标投票决策
    MultiTargetVoting,
    /// 多等级分层分配决策
    HierarchicalDistribution,
    /// 单目标抽奖与补偿机制
    SingleTargetWithCompensation,
    /// 扑克牌洗牌与一次性分配
    PokerShuffleOneTime,
    /// 扑克牌洗牌与顺序多次分配
    PokerShuffleSequential,
}

impl DDAlgorithmType {
    /// 将算法类型转换为字符串表示
    pub fn as_str(&self) -> &'static str {
        match self {
            DDAlgorithmType::SingleTargetLottery => "single_target_lottery",
            DDAlgorithmType::MultiTargetLottery => "multi_target_lottery",
            DDAlgorithmType::MultiLevelLottery => "multi_level_lottery",
            DDAlgorithmType::MultiTargetVoting => "multi_target_voting",
            DDAlgorithmType::HierarchicalDistribution => "hierarchical_distribution",
            DDAlgorithmType::SingleTargetWithCompensation => "single_target_with_compensation",
            DDAlgorithmType::PokerShuffleOneTime => "poker_shuffle_one_time",
            DDAlgorithmType::PokerShuffleSequential => "poker_shuffle_sequential",
        }
    }

    /// 返回所有已知的算法变体
    pub fn all() -> &'static [DDAlgorithmType] {
        use DDAlgorithmType::*;
        const VARIANTS: [DDAlgorithmType; 8] = [
            SingleTargetLottery,
            MultiTargetLottery,
            MultiLevelLottery,
            MultiTargetVoting,
            HierarchicalDistribution,
            SingleTargetWithCompensation,
            PokerShuffleOneTime,
            PokerShuffleSequential,
        ];
        &VARIANTS
    }
}

impl<'a> PrimaryKey<'a> for DDAlgorithmType {
    type Prefix = ();
    type SubPrefix = ();
    type Suffix = Self;
    type SuperSuffix = Self;

    /// 将算法类型转换为存储键
    fn key(&self) -> Vec<Key<'_>> {
        vec![Key::Ref(self.as_str().as_bytes())]
    }
}

impl KeyDeserialize for DDAlgorithmType {
    type Output = Self;
    const KEY_ELEMS: u16 = 1;

    /// 从字节向量反序列化算法类型
    fn from_vec(value: Vec<u8>) -> Result<Self, StdError> {
        let s = String::from_utf8(value)
            .map_err(|_| StdError::generic_err("DDAlgorithmType: invalid utf8"))?;
        match s.as_str() {
            "single_target_lottery" => Ok(DDAlgorithmType::SingleTargetLottery),
            "multi_target_lottery" => Ok(DDAlgorithmType::MultiTargetLottery),
            "multi_level_lottery" => Ok(DDAlgorithmType::MultiLevelLottery),
            "multi_target_voting" => Ok(DDAlgorithmType::MultiTargetVoting),
            "hierarchical_distribution" => Ok(DDAlgorithmType::HierarchicalDistribution),
            "single_target_with_compensation" => Ok(DDAlgorithmType::SingleTargetWithCompensation),
            "poker_shuffle_one_time" => Ok(DDAlgorithmType::PokerShuffleOneTime),
            "poker_shuffle_sequential" => Ok(DDAlgorithmType::PokerShuffleSequential),
            _ => Err(StdError::generic_err("DDAlgorithmType: unknown variant")),
        }
    }
}

// ==================== 奖品和奖励相关 ====================

#[cw_serde]
/// 奖励属性
pub struct RewardAttribute {
    /// 属性名称
    pub trait_type: String,
    /// 属性值
    pub value: String,
    /// 显示类型
    pub display_type: Option<String>,
}

#[cw_serde]
/// 投票奖励信息
pub struct VotingReward {
    /// 奖品名称
    pub name: String,
    /// 奖品描述
    pub description: String,
    /// 奖品图片URI
    pub image_uri: Option<String>,
    /// 奖品外部链接
    pub external_link: Option<String>,
    /// 奖品属性
    pub attributes: Option<Vec<RewardAttribute>>,
    /// 奖品背景颜色
    pub background_color: Option<String>,
    /// 奖品动画URL
    pub animation_url: Option<String>,
    /// 奖品YouTube视频URL
    pub youtube_url: Option<String>,
}

#[cw_serde]
/// 奖品元数据（存储在区块链上）
pub struct RewardMetadata {
    /// 奖品名称
    pub name: String,
    /// 奖品描述
    pub description: String,
    /// 奖品图片URI
    pub image_uri: Option<String>,
    /// 奖品外部链接
    pub external_link: Option<String>,
    /// 奖品属性
    pub attributes: Option<Vec<RewardAttribute>>,
    /// 奖品背景颜色
    pub background_color: Option<String>,
    /// 奖品动画URL
    pub animation_url: Option<String>,
    /// 奖品YouTube视频URL
    pub youtube_url: Option<String>,
    /// 铸造时间
    pub minted_at: Timestamp,
    /// 关联的抽奖会话ID
    pub lottery_session_id: String,
    /// 获奖者地址
    pub winner: String,
}

#[cw_serde]
/// 奖品分配策略
pub enum DistributionStrategy {
    /// 随机分配：随机选择获奖者
    Random,
    /// 按排名分配：按排名顺序分配奖品
    ByRank,
    /// 按权重分配：按权重比例分配奖品
    ByWeight,
    /// 自定义分配：由合约定义分配规则
    Custom(String),
}

#[cw_serde]
/// 奖品分配结果
pub struct RewardDistribution {
    /// 获奖者地址
    pub winner: String,
    /// 关联 token id
    pub token_id: String,
}

// ==================== 时间控制 ====================

#[cw_serde]
/// 时间控制模式
pub enum TimeControlMode {
    /// 基于区块高度的时间控制
    BlockHeight {
        /// 承诺阶段结束的区块高度
        commitment_height: u64,
        /// 揭示阶段结束的区块高度
        reveal_height: u64,
    },
    /// 基于时间间隔的时间控制
    TimeInterval {
        /// 承诺阶段持续时间（秒）
        commitment_duration: u64,
        /// 揭示阶段持续时间（秒）
        reveal_duration: u64,
    },
}

// ==================== 抽奖会话相关 ====================

#[cw_serde]
/// 抽奖会话状态
pub enum LotteryStatus {
    /// 已创建
    Created,
    /// 承诺阶段
    CommitmentPhase,
    /// 揭示阶段
    RevealPhase,
    /// 已完成
    Completed,
    /// 已取消
    Cancelled,
}

#[cw_serde]
/// 抽奖会话信息
pub struct LotterySessionInfo {
    /// 会话ID
    pub session_id: String,
    /// 会话标题
    pub title: String,
    /// 会话描述
    pub description: String,
    /// 创建者地址
    pub creator: String,
    /// 创建时间
    pub created_at: Timestamp,
    /// 奖品总数
    pub total_rewards: u32,
    /// 已铸造奖品数
    pub minted_rewards: u32,
}

#[cw_serde]
/// 抽奖会话
pub struct LotterySession {
    /// 会话ID
    pub session_id: String,
    /// 会话标题
    pub title: String,
    /// 会话描述
    pub description: String,
    /// 参与者地址列表
    pub participants: Vec<String>,
    /// 关联的NFT合约地址
    pub nft_contract: Option<String>,
    /// 创建者地址
    pub creator: String,
    /// 会话状态
    pub status: LotteryStatus,
    /// 创建时间
    pub created_at: Timestamp,
    /// 创建时的区块高度
    pub created_height: u64,
    /// 时间控制模式
    pub time_control: TimeControlMode,
    /// 承诺阶段截止时间
    pub commitment_deadline: Option<Timestamp>,
    /// 揭示阶段截止时间
    pub reveal_deadline: Option<Timestamp>,
    /// 承诺阶段截止区块高度
    pub commitment_deadline_height: Option<u64>,
    /// 揭示阶段截止区块高度
    pub reveal_deadline_height: Option<u64>,
    /// 奖品信息
    pub reward: VotingReward,
    /// 抽奖结果
    pub result: Option<LotteryResult>,
}

#[cw_serde]
/// 抽奖结果
pub struct LotteryResult {
    /// 会话ID
    pub session_id: String,
    /// 获奖者地址
    pub winner: String,
    /// 随机种子
    pub random_seed: u64,
    /// 随机数
    pub random_number: u64,
    /// 结果哈希
    pub result_hash: String,
    /// 总参与者数量
    pub total_participants: u32,
    /// 执行时间
    pub executed_at: Timestamp,
    /// 算法类型
    pub algorithm_type: String,
}

// ==================== NFT合约接口 ====================

#[cw_serde]
/// NFT合约实例化消息
pub struct NftInstantiateMsg {
    /// 合约名称
    pub name: String,
    /// 合约符号
    pub symbol: String,
    /// 铸造者地址
    pub minter: String,
    /// 参与者地址列表
    pub participants: Vec<String>,
    /// 最大参与者数量
    pub max_participants: u32,
    /// 会话是否激活
    pub session_active: Option<bool>,
}

#[cw_serde]
/// NFT合约执行消息
pub enum NftExecuteMsg {
    // 投票相关
    /// 提交承诺
    SubmitCommitment {
        /// 承诺哈希
        commitment_hash: String,
        /// 盐值
        salt: String,
    },
    /// 提交揭示
    SubmitReveal {
        /// 投票数据
        vote_data: Binary,
        /// 盐值
        salt: String,
    },

    // 参与者管理（仅管理员）
    /// 添加单个参与者
    AddParticipant {
        /// 参与者地址
        participant: String,
    },
    /// 批量添加参与者
    AddParticipants {
        /// 参与者地址列表
        participants: Vec<String>,
    },
    /// 移除参与者
    RemoveParticipant {
        /// 参与者地址
        participant: String,
    },

    // NFT转移控制（仅管理员）
    /// 设置转移锁定状态
    SetTransfersLocked {
        /// 是否锁定
        locked: bool,
    },
    /// 设置会话激活状态
    SetSessionActive {
        /// 是否激活
        active: bool,
    },

    // NFT转移（公开）
    /// 转移NFT
    TransferNft {
        /// 接收者地址
        recipient: String,
        /// Token ID
        token_id: String,
    },
}

#[cw_serde]
/// NFT合约查询消息
pub enum NftQueryMsg {
    // 参与者相关
    /// 获取所有参与者
    GetParticipants {},
    /// 检查是否为参与者
    IsParticipant { participant: String },
    /// 获取参与者数量
    GetParticipantCount {},
    /// 获取最大参与者数量
    GetMaxParticipants {},
    /// 获取参与者索引
    GetParticipantIndex { address: String },

    // 投票数据相关
    /// 获取参与者的承诺
    GetCommitment { participant: String },
    /// 获取参与者的揭示
    GetReveal { participant: String },
    /// 获取所有承诺
    GetAllCommitments {},
    /// 获取所有揭示
    GetAllReveals {},
    /// 检查是否有承诺
    HasCommitment { participant: String },
    /// 检查是否有揭示
    HasReveal { participant: String },

    // 会话状态
    /// 获取会话激活状态
    GetSessionActive {},
    /// 获取转移锁定状态
    GetTransfersLocked {},
    /// 获取会话元数据
    GetSessionMeta {},

    // NFT相关
    /// 获取NFT所有者
    OwnerOf { token_id: String },

    // 时间相关
    /// 获取当前时间
    GetCurrentTime {},
    /// 获取当前区块高度
    GetCurrentHeight {},

    // 批量查询
    /// 检查是否可以添加参与者
    CanAddParticipants { count: u32 },
    /// 获取投票状态
    GetVotingStatus {},
}

#[cw_serde]
/// 会话元数据
pub struct NftSessionMeta {
    /// 参与者地址列表
    pub participants: Vec<String>,
    /// 最大参与者数量
    pub max_participants: u32,
    /// 会话是否激活
    pub session_active: bool,
}

#[cw_serde]
/// 承诺信息
pub struct CommitmentInfo {
    /// 参与者地址
    pub participant: String,
    /// 承诺哈希
    pub commitment_hash: String,
    /// 盐值
    pub salt: String,
    /// 提交时间
    pub submitted_at: u64,
}

#[cw_serde]
/// 揭示信息
pub struct RevealInfo {
    /// 参与者地址
    pub participant: String,
    /// 投票数据
    pub vote_data: Binary,
    /// 盐值
    pub salt: String,
    /// 提交时间
    pub submitted_at: u64,
}

#[cw_serde]
/// 投票状态
pub struct VotingStatus {
    /// 总参与者数量
    pub total_participants: u32,
    /// 承诺数量
    pub commitments_count: u32,
    /// 揭示数量
    pub reveals_count: u32,
    /// 会话是否激活
    pub session_active: bool,
    /// 是否所有参与者都已承诺
    pub all_committed: bool,
    /// 是否所有参与者都已揭示
    pub all_revealed: bool,
}

// ==================== 主控合约接口 ====================

#[cw_serde]
/// 主控合约实例化消息
pub struct MainInstantiateMsg {
    /// 管理员地址
    pub admin: String,
    /// 最小参与者数量
    pub min_participants: u32,
    /// 最大参与者数量
    pub max_participants: u32,
    /// 默认时间控制模式
    pub default_time_control: TimeControlMode,
    /// 费用金额
    pub fee_amount: Option<Uint128>,
    /// 奖品NFT合约地址
    pub reward_nft_contract: Option<String>,
}

#[cw_serde]
/// 主控合约执行消息
pub enum MainExecuteMsg {
    // 会话管理
    /// 从NFT合约创建抽奖
    CreateLotteryFromNft {
        /// 标题
        title: String,
        /// 描述
        description: String,
        /// NFT合约地址
        nft_contract: String,
        /// 时间控制模式
        time_control: Option<TimeControlMode>,
        /// 奖品信息
        reward: VotingReward,
    },
    /// 执行抽奖
    ExecuteLottery {
        /// 会话ID
        session_id: String,
        /// 随机种子
        random_seed: Option<u64>,
    },
    /// 取消抽奖
    CancelLottery {
        /// 会话ID
        session_id: String,
    },

    // 奖品管理
    /// 创建奖品NFT
    CreateRewardNft {
        /// 会话ID
        session_id: String,
    },

    // 配置管理（仅管理员）
    /// 更新配置
    UpdateConfig {
        /// 最小参与者数量
        min_participants: Option<u32>,
        /// 最大参与者数量
        max_participants: Option<u32>,
        /// 默认时间控制模式
        default_time_control: Option<TimeControlMode>,
        /// 费用金额
        fee_amount: Option<Uint128>,
    },
    /// 暂停合约
    PauseContract {},
    /// 恢复合约
    ResumeContract {},
}

#[cw_serde]
/// 主控合约查询消息
pub enum MainQueryMsg {
    /// 获取抽奖会话
    GetLotterySession { session_id: String },
    /// 获取抽奖结果
    GetLotteryResult { session_id: String },
    /// 列出会话
    ListSessions {
        /// 起始位置
        start_after: Option<String>,
        /// 限制数量
        limit: Option<u32>,
        /// 状态过滤
        status: Option<LotteryStatus>,
    },
    /// 获取合约统计
    GetContractStats {},
    /// 获取配置
    GetConfig {},
    /// 获取参与者
    GetParticipants { session_id: String },
    /// 检查承诺阶段是否结束
    IsCommitmentPhaseEnded { session_id: String },
    /// 检查揭示阶段是否结束
    IsRevealPhaseEnded { session_id: String },
    /// 获取当前时间
    GetCurrentTime {},
    /// 获取当前区块高度
    GetCurrentHeight {},

    // 从NFT合约查询投票数据
    /// 获取NFT参与者
    GetNftParticipants { nft_contract: String },
    /// 检查是否为NFT参与者
    IsNftParticipant {
        nft_contract: String,
        participant: String,
    },
    /// 获取NFT投票状态
    GetNftVotingStatus { nft_contract: String },
}

#[cw_serde]
/// 合约配置
pub struct Config {
    /// 管理员地址
    pub admin: Addr,
    /// 最小参与者数量
    pub min_participants: u32,
    /// 最大参与者数量
    pub max_participants: u32,
    /// 默认时间控制模式
    pub default_time_control: TimeControlMode,
    /// 费用金额
    pub fee_amount: Option<Uint128>,
    /// 是否暂停
    pub paused: bool,
    /// 奖品NFT合约地址
    pub reward_nft_contract: Option<String>,
}

#[cw_serde]
/// 合约统计
pub struct ContractStats {
    /// 总会话数
    pub total_sessions: u64,
    /// 活跃会话数
    pub active_sessions: u64,
    /// 已完成会话数
    pub completed_sessions: u64,
    /// 已取消会话数
    pub cancelled_sessions: u64,
    /// 总参与者数
    pub total_participants: u64,
}

// ==================== 奖品NFT合约接口 ====================

#[cw_serde]
/// 奖品NFT元数据
pub struct RewardNftMetadata {
    /// 名称
    pub name: String,
    /// 描述
    pub description: String,
    /// 图片URI
    pub image_uri: Option<String>,
    /// 外部链接
    pub external_link: Option<String>,
    /// 属性列表
    pub attributes: Option<Vec<RewardNftAttribute>>,
    /// 背景颜色
    pub background_color: Option<String>,
    /// 动画URL
    pub animation_url: Option<String>,
    /// YouTube视频URL
    pub youtube_url: Option<String>,
    /// 铸造时间
    pub minted_at: Timestamp,
    /// 抽奖会话ID
    pub lottery_session_id: String,
    /// 获奖者地址
    pub winner: String,
}

#[cw_serde]
/// 奖品NFT属性
pub struct RewardNftAttribute {
    /// 属性类型
    pub trait_type: String,
    /// 属性值
    pub value: String,
    /// 显示类型
    pub display_type: Option<String>,
}

#[cw_serde]
/// 奖品NFT执行消息
pub enum RewardExecuteMsg {
    /// 铸造奖品
    MintReward {
        /// Token ID
        token_id: String,
        /// 获奖者地址
        winner: String,
        /// 抽奖会话ID
        lottery_session_id: String,
        /// 元数据
        metadata: RewardNftMetadata,
    },
}

// ==================== 算法相关 ====================

#[cw_serde]
/// 单目标算法参数
pub struct SingleTargetParams {
    /// 参与者地址列表
    pub participants: Vec<String>,
    /// 投票值列表（揭示值）- 必需，用于累加计算
    pub vote_values: Option<Vec<u64>>,
    /// 随机种子
    pub random_seed: Option<u64>,
    /// 权重列表
    pub weights: Option<Vec<u32>>,
}

#[cw_serde]
/// 单目标算法结果
pub struct SingleTargetResult {
    /// 获奖者地址
    pub winner: String,
    /// 随机种子
    pub random_seed: u64,
    /// 结果哈希
    pub result_hash: String,
    /// 随机数
    pub random_number: u64,
    /// 总参与者数量
    pub total_participants: u32,
}

// ==================== 错误类型 ====================

#[cw_serde]
/// 合约错误类型
pub enum ContractError {
    /// 未授权
    Unauthorized,
    /// 会话未找到
    SessionNotFound,
    /// 参与者未找到
    ParticipantNotFound,
    /// 无效状态
    InvalidState,
    /// 时间未到
    TimeNotReached,
    /// 已投票
    AlreadyVoted,
    /// 无效承诺
    InvalidCommitment,
    /// 参与者不足
    InsufficientParticipants,
    /// 参与者过多
    TooManyParticipants,
    /// 合约已暂停
    ContractPaused,
    /// 无效地址
    InvalidAddress,
    /// 重复参与者
    DuplicateParticipant,
    /// 无法移除已投票参与者
    CannotRemoveVotedParticipant,
    /// 达到最大参与者数量
    MaximumParticipantsReached,
    /// 奖品NFT未配置
    RewardNftNotConfigured,
    /// 仅管理员可执行
    OnlyAdminCanExecute,
    /// 仅创建者可取消
    OnlyCreatorCanCancel,
    /// 无法取消已完成的抽奖
    CannotCancelCompletedLottery,
    /// 完成后无法创建奖品
    CannotCreateRewardAfterCompletion,
    /// 并非所有参与者都已揭示
    NotAllParticipantsRevealed,
    /// 无效承诺验证
    InvalidCommitmentVerification,
    /// 必须先提交承诺
    MustSubmitCommitmentFirst,
    /// 承诺已提交
    CommitmentAlreadySubmitted,
    /// 揭示已提交
    RevealAlreadySubmitted,
    /// 会话未激活
    SessionNotActive,
    /// 转移已锁定
    TransfersLocked,
    /// 仅管理员可设置锁定
    OnlyAdminCanSetLock,
    /// 仅管理员可设置会话激活
    OnlyAdminCanSetSessionActive,
    /// 仅管理员可添加参与者
    OnlyAdminCanAddParticipants,
    /// 仅管理员可移除参与者
    OnlyAdminCanRemoveParticipants,
    /// 仅管理员可更新配置
    OnlyAdminCanUpdateConfig,
    /// 仅管理员可暂停合约
    OnlyAdminCanPauseContract,
    /// 仅管理员可恢复合约
    OnlyAdminCanResumeContract,
    /// 仅管理员可创建奖品NFT
    OnlyAdminCanCreateRewardNft,
    /// 通用错误
    Generic(String),
}

impl From<ContractError> for cosmwasm_std::StdError {
    /// 将合约错误转换为标准错误
    fn from(err: ContractError) -> Self {
        match err {
            ContractError::Unauthorized => StdError::generic_err("Unauthorized"),
            ContractError::SessionNotFound => StdError::generic_err("Session not found"),
            ContractError::ParticipantNotFound => StdError::generic_err("Participant not found"),
            ContractError::InvalidState => StdError::generic_err("Invalid state"),
            ContractError::TimeNotReached => StdError::generic_err("Time not reached"),
            ContractError::AlreadyVoted => StdError::generic_err("Already voted"),
            ContractError::InvalidCommitment => StdError::generic_err("Invalid commitment"),
            ContractError::InsufficientParticipants => {
                StdError::generic_err("Insufficient participants")
            }
            ContractError::TooManyParticipants => StdError::generic_err("Too many participants"),
            ContractError::ContractPaused => StdError::generic_err("Contract is paused"),
            ContractError::InvalidAddress => StdError::generic_err("Invalid address"),
            ContractError::DuplicateParticipant => StdError::generic_err("Duplicate participant"),
            ContractError::CannotRemoveVotedParticipant => {
                StdError::generic_err("Cannot remove voted participant")
            }
            ContractError::MaximumParticipantsReached => {
                StdError::generic_err("Maximum participants reached")
            }
            ContractError::RewardNftNotConfigured => {
                StdError::generic_err("Reward NFT not configured")
            }
            ContractError::OnlyAdminCanExecute => StdError::generic_err("Only admin can execute"),
            ContractError::OnlyCreatorCanCancel => StdError::generic_err("Only creator can cancel"),
            ContractError::CannotCancelCompletedLottery => {
                StdError::generic_err("Cannot cancel completed lottery")
            }
            ContractError::CannotCreateRewardAfterCompletion => {
                StdError::generic_err("Cannot create reward after completion")
            }
            ContractError::NotAllParticipantsRevealed => {
                StdError::generic_err("Not all participants revealed")
            }
            ContractError::InvalidCommitmentVerification => {
                StdError::generic_err("Invalid commitment verification")
            }
            ContractError::MustSubmitCommitmentFirst => {
                StdError::generic_err("Must submit commitment first")
            }
            ContractError::CommitmentAlreadySubmitted => {
                StdError::generic_err("Commitment already submitted")
            }
            ContractError::RevealAlreadySubmitted => {
                StdError::generic_err("Reveal already submitted")
            }
            ContractError::SessionNotActive => StdError::generic_err("Session not active"),
            ContractError::TransfersLocked => StdError::generic_err("Transfers locked"),
            ContractError::OnlyAdminCanSetLock => StdError::generic_err("Only admin can set lock"),
            ContractError::OnlyAdminCanSetSessionActive => {
                StdError::generic_err("Only admin can set session active")
            }
            ContractError::OnlyAdminCanAddParticipants => {
                StdError::generic_err("Only admin can add participants")
            }
            ContractError::OnlyAdminCanRemoveParticipants => {
                StdError::generic_err("Only admin can remove participants")
            }
            ContractError::OnlyAdminCanUpdateConfig => {
                StdError::generic_err("Only admin can update config")
            }
            ContractError::OnlyAdminCanPauseContract => {
                StdError::generic_err("Only admin can pause contract")
            }
            ContractError::OnlyAdminCanResumeContract => {
                StdError::generic_err("Only admin can resume contract")
            }
            ContractError::OnlyAdminCanCreateRewardNft => {
                StdError::generic_err("Only admin can create reward NFT")
            }
            ContractError::Generic(msg) => StdError::generic_err(msg),
        }
    }
}

// ==================== 工具函数 ====================

/// 验证承诺哈希
pub fn verify_commitment(commitment_hash: &str, vote_data: &[u8], salt: &str) -> bool {
    use sha2::{Digest, Sha256};
    let mut hasher = Sha256::new();
    hasher.update(vote_data);
    hasher.update(salt.as_bytes());
    let calculated_hash = format!("{:x}", hasher.finalize());
    calculated_hash == commitment_hash
}

/// 生成承诺哈希
pub fn generate_commitment_hash(vote_data: &[u8], salt: &str) -> String {
    use sha2::{Digest, Sha256};
    let mut hasher = Sha256::new();
    hasher.update(vote_data);
    hasher.update(salt.as_bytes());
    format!("{:x}", hasher.finalize())
}

/// 生成随机种子
pub fn generate_random_seed(block_hash: &str, timestamp: u64) -> u64 {
    use sha2::{Digest, Sha256};
    let mut hasher = Sha256::new();
    hasher.update(block_hash.as_bytes());
    hasher.update(timestamp.to_be_bytes());
    let hash = hasher.finalize();

    let mut seed_bytes = [0u8; 8];
    seed_bytes.copy_from_slice(&hash[0..8]);
    u64::from_be_bytes(seed_bytes)
}

/// 验证参与者地址唯一性（CosmWasm 兼容版本）
pub fn validate_unique_participants(participants: &[String]) -> Result<(), ContractError> {
    for i in 0..participants.len() {
        for j in (i + 1)..participants.len() {
            if participants[i] == participants[j] {
                return Err(ContractError::DuplicateParticipant);
            }
        }
    }
    Ok(())
}

/// 验证参与者数量
pub fn validate_participant_count(
    participants: &[String],
    min_participants: u32,
    max_participants: u32,
) -> Result<(), ContractError> {
    let count = participants.len() as u32;

    if count < min_participants {
        return Err(ContractError::InsufficientParticipants);
    }

    if count > max_participants {
        return Err(ContractError::TooManyParticipants);
    }

    Ok(())
}

/// 创建默认奖品信息
pub fn create_default_reward() -> VotingReward {
    VotingReward {
        name: "Default Reward".to_string(),
        description: "A default reward for lottery winners".to_string(),
        image_uri: None,
        external_link: None,
        attributes: None,
        background_color: None,
        animation_url: None,
        youtube_url: None,
    }
}

/// 创建示例奖品信息
pub fn create_example_reward() -> VotingReward {
    VotingReward {
        name: "Lucky Winner NFT".to_string(),
        description: "A special NFT for the lottery winner".to_string(),
        image_uri: Some("https://example.com/winner-nft.png".to_string()),
        external_link: Some("https://example.com/winner-info".to_string()),
        attributes: Some(vec![
            RewardAttribute {
                trait_type: "Rarity".to_string(),
                value: "Legendary".to_string(),
                display_type: Some("string".to_string()),
            },
            RewardAttribute {
                trait_type: "Power Level".to_string(),
                value: "100".to_string(),
                display_type: Some("number".to_string()),
            },
        ]),
        background_color: Some("#FFD700".to_string()),
        animation_url: Some("https://example.com/winner-animation.mp4".to_string()),
        youtube_url: Some("https://youtube.com/watch?v=winner".to_string()),
    }
}
