use serde::{Deserialize, Serialize};
use steel::*;

use crate::state::vote_pda;
use super::GovernanceAccount;

/// Vote account (one per user per proposal)
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct Vote {
    /// Proposal ID this vote is for
    pub proposal_id: u64,
    
    /// Voter's public key
    pub voter: Pubkey,
    
    /// Voting power (stake score = balance * multiplier at time of vote)
    /// This is the sum of all stake scores across all stake accounts for the voter
    pub voting_power: u64,
    
    /// Vote choice (as u8)
    pub choice: u8,
    
    /// Buffer field for future use (includes padding for alignment)
    pub buffer_a: [u8; 7],  // 7 bytes padding + future use
    
    /// Timestamp when vote was cast
    pub voted_at: u64,
    
    /// Buffer fields for future use
    pub buffer_b: u64,
    pub buffer_c: u64,
}

impl Vote {
    pub fn pda(proposal_id: u64, voter: Pubkey) -> (Pubkey, u8) {
        vote_pda(proposal_id, voter)
    }
    
    /// Get choice as enum
    pub fn choice(&self) -> Result<VoteChoice, ProgramError> {
        VoteChoice::try_from(self.choice)
            .map_err(|_| ProgramError::InvalidAccountData)
    }
}

/// Vote choice
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, IntoPrimitive, TryFromPrimitive, Serialize, Deserialize)]
pub enum VoteChoice {
    Yes = 0,
    No = 1,
    Abstain = 2,
}

account!(GovernanceAccount, Vote);
