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

use crate::state::{rig_pda, Treasury};

use super::OilAccount;

/// Rig account for auction-based mining
/// Similar to Driller but focused on auction wells
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
pub struct Rig {
    /// The authority of this rig account (owner's wallet).
    pub authority: Pubkey,

    /// OIL rewards from auction wells (not yet claimed)
    /// Accumulated when ownership changes (pre-minted) or when claiming current ownership (minted on-demand)
    pub auction_rewards_oil: u64,

    /// SOL rewards from auction wells (not yet claimed)
    /// Includes: outbid refunds, pool refunds from abandoned pools
    pub auction_rewards_sol: u64,

    /// Current pool contributions per well (in lamports)
    /// [well_0, well_1, well_2, well_3]
    /// 0 = not contributing to this well
    pub auction_pool_contributions: [u64; 4],

    /// Epoch ID per well that user contributed to
    /// [epoch_0, epoch_1, epoch_2, epoch_3]
    /// 0 = not contributing to this well
    /// Used to determine if pool is still active (compare with Well.epoch_id)
    pub auction_pool_epochs: [u64; 4],

    /// The rewards factor last time auction rewards were updated on this rig account.
    pub auction_rewards_factor: Numeric,

    /// The amount of OIL this rig has earned from auction claim fees (refined OIL).
    pub auction_refined_oil: u64,

    /// The last time this rig claimed OIL rewards.
    pub last_claim_oil_at: i64,

    /// The last time this rig claimed SOL rewards.
    pub last_claim_sol_at: i64,

    /// The total amount of OIL this rig has mined across all auction wells (lifetime).
    pub lifetime_rewards_oil: u64,

    /// The total amount of SOL this rig has earned across all auction wells (lifetime).
    /// Includes: outbid refunds, pool refunds, etc.
    pub lifetime_rewards_sol: u64,

    /// Last epoch ID per well that this rig synced (similar to checkpoint_id in Driller)
    /// [epoch_0, epoch_1, epoch_2, epoch_3]
    /// 0 = not synced for this well
    /// Used to enforce sync_auction_state before set_bid/join_auction_pool (like checkpoint before deploy)
    /// Ensures each user syncs their own refunds before participating in auctions
    pub last_synced_epoch_id: [u64; 4],
}

impl Rig {
    pub fn pda(&self) -> (Pubkey, u8) {
        rig_pda(self.authority)
    }

    pub fn update_auction_rewards(&mut self, treasury: &Treasury) {
        // Accumulate auction rewards, weighted by unclaimed auction OIL.
        if treasury.auction_driller_rewards_factor > self.auction_rewards_factor {
            let accumulated_rewards = treasury.auction_driller_rewards_factor - self.auction_rewards_factor;
            if accumulated_rewards < Numeric::ZERO {
                panic!("Accumulated auction rewards is negative");
            }
            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.auction_rewards_oil);
            self.auction_refined_oil += personal_rewards.to_u64();
        }

        // Update this rig account's last seen auction rewards factor.
        self.auction_rewards_factor = treasury.auction_driller_rewards_factor;
    }

    /// Credit a pool refund to this rig account
    /// Called when a pool the user contributed to is abandoned
    /// Updates rig state: credits refund amount and clears pool tracking fields
    pub fn credit_pool_refund(&mut self, well_id: usize, refund_amount: u64) {
        // Credit refund to rig's auction_rewards_sol
        self.auction_rewards_sol += refund_amount;
        
        // Clear rig tracking fields (pool is abandoned, user is no longer contributing)
        self.auction_pool_contributions[well_id] = 0;
        self.auction_pool_epochs[well_id] = 0;
    }
}

account!(OilAccount, Rig);
