package dev.banking;

import dev.banking.model.*;
import dev.banking.monitor.LiveMonitor;
import dev.banking.processor.TransactionProcessor;
import dev.banking.service.BankingSystem;

import java.util.*;
import java.util.concurrent.*;

/**
 * DemoApplication is responsible for:
 * - Building the system
 * - Running the simulation
 * - Managing lifecycle (threads, schedulers)
 */
public final class DemoApplication {

    private DemoApplication() {
    }

    public static void run() {

        System.out.println("Initializing Banking Simulation...\n");

        /*
         * 1. Create bank accounts
         */
        BankAccount acc1 = new BankAccount(1, 1000);
        BankAccount acc2 = new BankAccount(2, 2000);
        BankAccount acc3 = new BankAccount(3, 1500);

        Map<Integer, BankAccount> accounts = new HashMap<>();
        accounts.put(1, acc1);
        accounts.put(2, acc2);
        accounts.put(3, acc3);

        /*
         * 2. Create transactions
         */
        List<Transaction> transactions = List.of(
                new DepositTransaction(1, 200),
                new WithdrawTransaction(2, 300),
                new TransferTransaction(1, 2, 150),
                new TransferTransaction(2, 3, 400),
                new DepositTransaction(3, 500),
                new WithdrawTransaction(1, 100),
                new TransferTransaction(3, 1, 250)
        );

        /*
         * 3. Thread pool (workers)
         */
        ExecutorService executor = Executors.newFixedThreadPool(4);

        /*
         * 4. Processor
         */
        TransactionProcessor processor = new TransactionProcessor(accounts);

        /*
         * 5. Banking system
         */
        BankingSystem bankingSystem = new BankingSystem(executor, processor);

        /*
         * 6. Live monitor (UI simulation)
         */
        LiveMonitor monitor = new LiveMonitor();

        ScheduledExecutorService monitorExecutor = Executors.newSingleThreadScheduledExecutor();

        monitorExecutor.scheduleAtFixedRate(() -> {
            monitor.update(accounts.values());
            System.out.println("----------------------");
        }, 0, 1, TimeUnit.SECONDS);

        /*
         * 7. Run simulation
         */
        bankingSystem.processTransactions(transactions);

        /*
         * 8. Shutdown / lifecycle management
         */
        shutdown(executor, monitorExecutor);

        System.out.println("\nSimulation completed.");
    }

    private static void shutdown(
            ExecutorService executor,
            ScheduledExecutorService monitorExecutor
    ) {
        try {
            executor.shutdown();
            executor.awaitTermination(5, TimeUnit.SECONDS);

            monitorExecutor.shutdown();
            monitorExecutor.awaitTermination(5, TimeUnit.SECONDS);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}