use steel::*;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
pub enum OilInstruction {
    // Driller
    Automate = 0,
    Initialize = 1,
    Checkpoint = 2,
    ClaimSOL = 3,
    ClaimOIL = 4,
    Close = 5,
    Deploy = 6,
    Log = 8,
    Reset = 9,
    ReloadSOL = 21,
    CreateReferral = 27,
    ClaimReferral = 28,

    // Auction-based mining
    SetBid = 29,
    JoinAuctionPool = 30,
    ClaimAuctionOIL = 31,
    ClaimAuctionSOL = 32,
    SyncAuctionState = 34,

    // Staker
    Deposit = 10,
    Withdraw = 11,
    ClaimYield = 12,

    // Admin
    Buyback = 13,
    SetAdmin = 15,
    SetFeeCollector = 16,
    SetSwapProgram = 17,
    SetVarAddress = 18,
    NewVar = 19,
    SetAdminFee = 20,
    Migrate = 26,
    SetAuction = 33,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Automate {
    pub amount: [u8; 8],
    pub deposit: [u8; 8],
    pub fee: [u8; 8],
    pub mask: [u8; 8],
    pub strategy: u8,
    pub reload: [u8; 8],
    /// Optional referrer pubkey for new drillers. Set to Pubkey::default() for no referrer.
    pub referrer: [u8; 32],
    /// Whether automated deployments should be pooled (1 = pooled, 0 = not pooled).
    pub pooled: u8,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct InitRound {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimSOL {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimOIL {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Deploy {
    pub amount: [u8; 8],
    pub squares: [u8; 4],
    /// Optional referrer pubkey. Set to Pubkey::default() for no referrer.
    pub referrer: [u8; 32],
    /// Whether this deploy is pooled. 0 = solo, 1 = pooled.
    pub pooled: u8,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Log {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Reset {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Close {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Mine {
    pub nonce: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Swap {
    pub amount: [u8; 8],
    pub direction: u8,
    pub precision: u8,
    pub seed: [u8; 32],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Uncommit {
    pub amount: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetAdmin {
    pub admin: [u8; 32],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetFeeCollector {
    pub fee_collector: [u8; 32],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetFeeRate {
    pub fee_rate: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Buyback {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ReloadSOL {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Deposit {
    pub amount: [u8; 8],
    pub lock_duration_days: [u8; 8],  // 0 = no lock, 1-730 days
    pub stake_id: [u8; 8],  // Unique ID for this stake account (allows multiple stakes per user)
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Withdraw {
    pub amount: [u8; 8],
    pub stake_id: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimYield {
    pub amount: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Checkpoint {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct NewVar {
    pub id: [u8; 8],
    pub commit: [u8; 32],
    pub samples: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetAdminFee {
    pub admin_fee: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetSwapProgram {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetVarAddress {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Migrate {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct CreateReferral {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimReferral {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Initialize {
    pub barrel_authority: [u8; 32],
    pub fee_collector: [u8; 32],
    pub swap_program: [u8; 32],
    pub var_address: [u8; 32],
    pub admin_fee: [u8; 8],
    // Auction configuration (optional - only used if auction accounts need initialization)
    pub halving_period_seconds: [u8; 8],
    pub base_mining_rates: [[u8; 8]; 4],  // 4 wells
    pub auction_duration_seconds: [u8; 8],
    pub starting_prices: [[u8; 8]; 4],  // 4 wells
    pub min_pool_contribution: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetBid {
    pub square_id: [u8; 8],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct JoinAuctionPool {
    pub square_id: [u8; 8],
    pub amount: [u8; 8], // SOL amount in lamports
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimAuctionOIL {
    /// Well IDs to claim OIL from (0-3), can claim multiple at once
    /// Bitmask: bit 0 = well 0, bit 1 = well 1, etc.
    pub well_mask: u8,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct ClaimAuctionSOL {
    /// Reserved for future use (currently unused, but kept for consistency)
    pub _reserved: u8,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SetAuction {
    pub halving_period_seconds: [u8; 8],
    pub last_halving_time: [u8; 8],
    pub base_mining_rates: [[u8; 8]; 4],  // 4 wells
    pub auction_duration_seconds: [u8; 8],
    pub starting_prices: [[u8; 8]; 4],  // 4 wells
    pub min_pool_contribution: [u8; 8],
    pub well_id: [u8; 8],  // Well ID to update (0-3). If >= 4, only updates auction account.
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct SyncAuctionState {
    /// Well ID to sync (0-3). If well_id >= 4, syncs all wells.
    pub well_id: [u8; 8],
}

instruction!(OilInstruction, Automate);
instruction!(OilInstruction, Initialize);
instruction!(OilInstruction, Checkpoint);
instruction!(OilInstruction, ClaimSOL);
instruction!(OilInstruction, ClaimOIL);
instruction!(OilInstruction, ReloadSOL);
instruction!(OilInstruction, Deploy);
instruction!(OilInstruction, Log);
instruction!(OilInstruction, Buyback);
instruction!(OilInstruction, Reset);
instruction!(OilInstruction, Close);
instruction!(OilInstruction, SetAdmin);
instruction!(OilInstruction, SetFeeCollector);
instruction!(OilInstruction, Deposit);
instruction!(OilInstruction, Withdraw);
instruction!(OilInstruction, ClaimYield);
instruction!(OilInstruction, NewVar);
instruction!(OilInstruction, SetAdminFee);
instruction!(OilInstruction, SetSwapProgram);
instruction!(OilInstruction, SetVarAddress);
instruction!(OilInstruction, Migrate);
instruction!(OilInstruction, CreateReferral);
instruction!(OilInstruction, ClaimReferral);
instruction!(OilInstruction, SetBid);
instruction!(OilInstruction, JoinAuctionPool);
instruction!(OilInstruction, ClaimAuctionOIL);
instruction!(OilInstruction, ClaimAuctionSOL);
instruction!(OilInstruction, SetAuction);
instruction!(OilInstruction, SyncAuctionState);