use brk_error::Result;
use brk_indexer::Lengths;
use brk_traversable::Traversable;
use brk_types::Version;
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode};

use crate::{
    distribution::{
        metrics::ImportConfig,
        state::{CohortState, CostBasisOps, RealizedOps},
    },
    internal::ValuePerBlockCumulativeRolling,
    price,
};

#[derive(Traversable)]
pub struct ActivityMinimal<M: StorageMode = Rw> {
    pub transfer_volume: ValuePerBlockCumulativeRolling<M>,
}

impl ActivityMinimal {
    pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
        let v1 = Version::ONE;
        Ok(Self {
            transfer_volume: cfg.import("transfer_volume", v1)?,
        })
    }

    pub(crate) fn min_len(&self) -> usize {
        self.transfer_volume.cumulative.sats.height.len()
    }

    #[inline(always)]
    pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
        self.transfer_volume.push_block_sats(state.sent);
    }

    pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
        let inner = &mut self.transfer_volume.inner;
        vec![
            &mut inner.cumulative.sats.height as &mut dyn AnyStoredVec,
            &mut inner.cumulative.cents.height,
        ]
    }

    pub(crate) fn compute_from_stateful(
        &mut self,
        starting_lengths: &Lengths,
        others: &[&Self],
        exit: &Exit,
    ) -> Result<()> {
        self.transfer_volume
            .cumulative
            .sats
            .height
            .compute_sum_of_others(
                starting_lengths.height,
                &others
                    .iter()
                    .map(|v| &v.transfer_volume.cumulative.sats.height)
                    .collect::<Vec<_>>(),
                exit,
            )?;

        Ok(())
    }

    pub(crate) fn compute_rest_part1(
        &mut self,
        prices: &price::Vecs,
        starting_lengths: &Lengths,
        exit: &Exit,
    ) -> Result<()> {
        self.transfer_volume
            .compute_rest(starting_lengths.height, prices, exit)?;
        Ok(())
    }
}
