/**
 * @file IncomingTransactionsReader.java
 * @brief Logic for simulating real-time transaction ingestion.
 */

import java.io.InputStream;
import java.util.*;

/**
 * @class IncomingTransactionsReader
 * @brief Mocks an external data source (like an HTTP server) providing real-time transactions.
 *
 * This class implements the @c Iterator interface. It reads transaction data from a 
 * resource file on the classpath, parses the content, and provides an interface 
 * to stream these transactions into the system for processing.
 * 
 * @implements Iterator<Transaction>
 */
public class IncomingTransactionsReader implements Iterator<Transaction> {
    
    /** @brief The name of the file containing the mock transaction data. */
    private static final String INPUT_TRANSACTIONS_FILE = "user-transactions.txt";
    
    /** @brief Internal list to hold all loaded transaction objects. */
    private final List<Transaction> transactions;
    
    /** @brief Iterator used to provide transactions one by one to the caller. */
    private final Iterator<Transaction> transactionIterator;

    /**
     * @brief Constructor for IncomingTransactionsReader.
     * 
     * Initializes the reader by loading all transactions from the specified 
     * text file into an internal list.
     */
    public IncomingTransactionsReader(){
        this.transactions = loadTransactions();
        this.transactionIterator = transactions.iterator();
    }

    /**
     * @brief Loads and parses transaction data from a classpath resource.
     * 
     * Reads the @c user-transactions.txt file. Each line is expected to be 
     * space-separated in the format: "User Location Amount".
     * 
     * @details This method uses a @c Scanner to iterate through lines and 
     * constructs new @ref Transaction instances.
     * 
     * @return List<Transaction> An unmodifiable list of all transactions found in the file.
     */
    private List<Transaction> loadTransactions() {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(INPUT_TRANSACTIONS_FILE);

        if (inputStream == null) {
            System.err.println("Critical Error: " + INPUT_TRANSACTIONS_FILE + " not found!");
            return Collections.emptyList();
        }

        Scanner scanner = new Scanner(inputStream);
        List<Transaction> transactions = new ArrayList<>();

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            
            if (parts.length >= 3) {
                String user = parts[0];
                String transactionLocation = parts[1];
                double amount = Double.valueOf(parts[2]);
                transactions.add(new Transaction(user, amount, transactionLocation));
            }
        }

        return Collections.unmodifiableList(transactions);
    }

    /**
     * @brief Checks if there are more transactions available in the stream.
     * @return boolean True if another transaction exists, false otherwise.
     */
    @Override
    public boolean hasNext() {
        return transactionIterator.hasNext();
    }

    /**
     * @brief Retrieves the next available transaction.
     * @return Transaction The next transaction in the sequence.
     */
    @Override
    public Transaction next() {
        return transactionIterator.next();
    }
}