use solana_sdk::{
    instruction::{AccountMeta, Instruction},
    pubkey::Pubkey,
};

use crate::constants::Discriminator;
use crate::types::CurveUpdateOp;

/// Build a SubmitCurveUpdates instruction (discriminator 18).
///
/// Accounts (2): authority(signer), curveUpdates(w).
pub fn build_submit_curve_updates(
    authority: &Pubkey,
    curve_updates_pda: &Pubkey,
    ops: &[CurveUpdateOp],
    program_id: &Pubkey,
) -> Instruction {
    let mut data = Vec::with_capacity(2 + ops.len() * 24);
    data.push(Discriminator::SubmitCurveUpdates as u8);
    data.push(ops.len() as u8);

    for op in ops {
        data.push(op.curve_type as u8);
        data.push(op.op_kind as u8);
        data.push(op.point_index);
        data.push(op.interpolation as u8);
        data.extend_from_slice(&op.amount_in.to_le_bytes());
        data.extend_from_slice(&op.price_factor_q32.to_le_bytes());
        data.extend_from_slice(&op.params);
    }

    let keys = vec![
        AccountMeta::new_readonly(*authority, true),
        AccountMeta::new(*curve_updates_pda, false),
    ];

    Instruction {
        program_id: *program_id,
        accounts: keys,
        data,
    }
}

/// Build an ApplyCurveUpdates instruction (discriminator 19).
///
/// Accounts (4): authority(signer), curveMeta, curvePrefabs(w), curveUpdates(w).
pub fn build_apply_curve_updates(
    authority: &Pubkey,
    curve_meta_pda: &Pubkey,
    curve_prefabs_pda: &Pubkey,
    curve_updates_pda: &Pubkey,
    program_id: &Pubkey,
) -> Instruction {
    let data = vec![Discriminator::ApplyCurveUpdates as u8];

    let keys = vec![
        AccountMeta::new_readonly(*authority, true),
        AccountMeta::new_readonly(*curve_meta_pda, false),
        AccountMeta::new(*curve_prefabs_pda, false),
        AccountMeta::new(*curve_updates_pda, false),
    ];

    Instruction {
        program_id: *program_id,
        accounts: keys,
        data,
    }
}
