//! Instruction discriminators + payload types.

use steel::*;

/// One-time setup: creates `Treasury` PDA + treasury USDC ATA. `payer` must be `ADMIN_ADDRESS`.
///
/// **Accounts:** `payer`, `treasury`, `mint`, `treasury_ata`, `system_program`, `token_program`,
/// `ata_program`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Initialize {}

/// Purchase tickets (gaming credits) with USDC.
///
/// Buying tickets is separate from placing a bet. The user first buys credits here
/// (on-chain, USDC split immediately), then places bets off-chain via the server
/// using those credits.
///
/// 1. Transfers `amount` µUSDC from the user's ATA into the treasury ATA.
/// 2. Updates `Treasury` PDA counters: `daily_jackpot += 70%`, `weekly_jackpot += 15%`,
///    `buyback += 10%`.
/// 3. Forwards the team share (5%) from the treasury ATA to `FEE_COLLECTOR` (CPI).
/// 4. Creates or increments the user's `UserCredits` PDA (`total_purchased += amount`).
/// 5. Emits `TicketPurchased { user, amount }`.
///
/// The indexer reads `TicketPurchased` events to credit the user's off-chain spendable
/// balance. Bets are placed and debited server-side against that balance.
///
/// **Accounts:** `user` (signer/payer), `user_ata`, `treasury`, `treasury_ata`, `credits`,
///               `fee_collector_ata`, `mint`, `token_program`, `system_program`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct BuyTicket {
    /// Amount in µUSDC (6 decimals).
    pub amount: [u8; 8],
}

/// Route claimed DBC / DAMM v2 trading fees into the treasury and split them on-chain.
///
/// The executor bot claims pool creator/LP fees off-chain via the Meteora SDK, receiving USDC
/// into its own ATA. This instruction then:
///   1. Transfers `amount` µUSDC from the executor's ATA into the treasury ATA (CPI).
///   2. Splits the amount according to `TICKET_*_BPS` and updates `Treasury` counters.
///   3. Forwards the team share (5%) from the treasury ATA to `FEE_COLLECTOR` (CPI).
///   4. Emits `FeesRouted`.
///
/// **Accounts:** `executor` (signer), `executor_ata`, `treasury`, `treasury_ata`,
///               `fee_collector_ata`, `mint`, `token_program`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct AdminRouteFees {
    pub amount: [u8; 8],
}

/// Pay `amount` µUSDC from the treasury ATA to `recipient_ata`. Used for winner payouts and
/// jackpot distributions. Only `EXECUTOR_ADDRESS` may sign.
///
/// **Accounts:** `executor` (signer), `treasury`, `treasury_ata`, `recipient_ata`, `mint`,
/// `token_program`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct AdminPayout {
    pub amount: [u8; 8],
    pub series_id: [u8; 2],
    pub _pad_ix: [u8; 6],
    pub period: [u8; 8],
}

/// Place one bet for the current round.
///
/// Rules enforced on-chain:
///   1. `User.balance >= TICKET_PRICE_MICROS` (must have at least 1 ticket).
///   2. `User.last_bet_period != period` (one bet per round, no double-betting).
///   3. Debits exactly `TICKET_PRICE_MICROS` from `User.balance`.
///   4. Sets `User.last_bet_period = period`.
///   5. Emits `BetPlaced { user, period, side }`.
///
/// The indexer reads `BetPlaced` to insert the bet into the DB and update market pools.
/// The server builds and returns an unsigned `PlaceBet` tx; the user signs in their wallet.
///
/// **Accounts:** `user` (signer), `user_pda`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct PlaceBet {
    /// 0 = UP, 1 = DOWN.
    pub side: u8,
    pub _pad: [u8; 1],
    /// Market series (always 0 for BTC/USD).
    pub series_id: [u8; 2],
    pub _pad2: [u8; 4],
    /// 5-min period number: `floor(unix_ts / 300)`.
    pub period: [u8; 8],
}

use num_enum::TryFromPrimitive;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
pub enum StreakInstruction {
    Initialize = 0,
    BuyTicket = 1,
    AdminRouteFees = 2,
    AdminPayout = 3,
    PlaceBet = 4,
}

instruction!(StreakInstruction, Initialize);
instruction!(StreakInstruction, BuyTicket);
instruction!(StreakInstruction, AdminRouteFees);
instruction!(StreakInstruction, AdminPayout);
instruction!(StreakInstruction, PlaceBet);
