package com.r35157.libs.jupiter.swap;

import com.r35157.libs.jupiter.JupiterTransactionOutcomeException;
import com.r35157.libs.valuetypes.basic.MoneyAmount;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.math.BigDecimal;

/**
 * Exchanges an exact human-readable token amount through Jupiter.
 *
 * <p>An input can be a supported SPL token or native SOL represented by
 * Jupiter's canonical SOL/WSOL mint
 * {@code So11111111111111111111111111111111111111112}. The canonical address
 * remains the {@code inputTokenMint} passed to the unchanged swap operation;
 * callers that select native SOL remain responsible for reading the native
 * wallet balance and applying their own reserve policy. Output remains a
 * supported SPL-token mint.</p>
 *
 * <p>The service resolves mint precision from Solana, obtains and validates a
 * Jupiter Swap V2 order, asks its configured wallet to sign the transaction,
 * submits the signed transaction through Jupiter's managed execution
 * endpoint, and independently awaits Solana confirmation. Legacy SPL-token
 * and Token-2022 behavior is unchanged.</p>
 */
public interface JupiterSwapService {
    /**
     * Swaps an exact amount of a supported token or native SOL into an SPL
     * token.
     *
     * <p>Native SOL input is expressed with the canonical SOL/WSOL mint
     * {@code So11111111111111111111111111111111111111112}; the service passes
     * that value unchanged to Jupiter as {@code inputMint}. No separate
     * native-SOL method is required.</p>
     *
     * <p>The returned amounts are the actual wallet-level amounts reported by
     * Jupiter after successful provider execution, not the quoted amounts.
     * Normal return additionally means the reported signature independently
     * reached Solana {@code CONFIRMED} success. A timed-out outcome or an I/O
     * error after submission can leave the transaction outcome unknown and
     * must never cause automatic resubmission.</p>
     *
     * @param inputTokenMint input SPL-token mint address, or the canonical
     *                       SOL/WSOL mint representing native SOL
     * @param inputTokenAmount exact input amount in human-readable token units
     * @param outputTokenMint output SPL-token mint address
     * @param maxSlippageBps maximum accepted slippage from 0 through 10000
     *                       basis points
     * @return confirmed transaction signature and actual amounts spent and
     *         received
     * @throws IllegalArgumentException if a mint, amount, or slippage value is
     *                                  invalid
     * @throws IllegalStateException if a mint does not exist, is owned by an
     *                               unsupported token program, or has invalid
     *                               metadata
     * @throws IOException if Solana or Jupiter communication, response
     *                     decoding, signing, execution, or confirmation fails;
     *                     after submission the on-chain outcome can be unknown
     * @throws JupiterTransactionOutcomeException if the submitted transaction
     *         definitively fails on-chain or confirmation times out with an
     *         unknown outcome
     * @throws InterruptedException if order pacing, Solana access, signing, or
     *                              Jupiter communication or confirmation is
     *                              interrupted; interruption propagates directly
     */
    @NotNull
    JupiterSwapResult swap(
            @NotNull ΩSPLMintAddressΩ inputTokenMint,
            @NotNull ΩAmountΩ inputTokenAmount,
            @NotNull ΩSPLMintAddressΩ outputTokenMint,
            int maxSlippageBps
    ) throws IOException, JupiterTransactionOutcomeException,
            InterruptedException;
}
