//! Protocol USDC bookkeeping (`treasury` PDA). **`BuyTickets`**, **`AdminInstantSettlement`**, and **`ClaimPositionFee`** update these counters; SPL USDC sits in the treasury ATA (**owner = this PDA**).
//!
//! Daily / weekly **winner lists and tier splits are computed off-chain**; **`ExecutorTreasury`** (**`JACKPOT_PAY`**) debits **`daily_jackpot`** / **`weekly_jackpot`** when the executor pays.

use steel::*;

use crate::consts::MAX_MARKET_SERIES;
use crate::error::StreakError;

use super::{treasury_pda, StreakAccount};

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct Treasury {
    /// **Daily jackpot** accruals (tickets + settlement subsidy); debited via **`ExecutorTreasury`** (**`JACKPOT_PAY`**, daily pool).
    pub daily_jackpot: u64,
    /// **Weekly jackpot** accruals (tickets + hook split); debited via **`ExecutorTreasury`** (**`JACKPOT_PAY`**, weekly pool).
    pub weekly_jackpot: u64,
    pub buyback: u64,
    /// Monotonic bookkeeping floor (`max` of **`period + 1`** pushed by **`MARKET_LINE_RELEASE`** and by settlement when **`winning_total == 0`**).
    ///
    /// **`InitMarket`** / **`PlaceBet`** do **not** require **`period == next_period[..]`**: many rounds may be deployed and traded like a listing grid; this cursor is ops / indexing only.
    pub next_period: [u64; MAX_MARKET_SERIES],
    /// Monotonically increasing week counter. Incremented by [`AdminNewWeek`](crate::instruction::AdminNewWeek)
    /// at the start of each scoring week (admin-gated, not time-derived on-chain).
    ///
    /// Each `Ledger` stores [`Ledger::week_number`](super::Ledger::week_number) and compares it
    /// against this value on every instruction that touches weekly stats; stale weekly counters
    /// are zeroed lazily (no all-ledger sweep needed).
    pub current_week: u64,
}

impl Treasury {
    pub fn pda() -> (Pubkey, u8) {
        treasury_pda()
    }

    #[inline(always)]
    pub fn series_index(series_id: u16) -> Result<usize, StreakError> {
        let i = series_id as usize;
        if i >= MAX_MARKET_SERIES {
            return Err(StreakError::InvalidMarketSeries);
        }
        Ok(i)
    }

    /// Advance **`next_period[slot]`** to at least **`settled_period + 1`** (no-op if already higher).
    #[inline(always)]
    pub fn bump_next_period_floor(
        &mut self,
        series_id: u16,
        settled_period: u64,
    ) -> Result<(), StreakError> {
        let i = Self::series_index(series_id)?;
        let n = settled_period.checked_add(1).ok_or(StreakError::Overflow)?;
        if n > self.next_period[i] {
            self.next_period[i] = n;
        }
        Ok(())
    }
}

account!(StreakAccount, Treasury);
