import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;

public class Capitulo16Projeto {
    interface Comando {
        String executar();
    }

    static final class RegistroComandos {
        private final Map<String, Comando> comandos = new LinkedHashMap<>();

        void registrar(String nome, Comando comando) {
            String chave = normalizar(nome);
            if (chave.isBlank()) {
                throw new IllegalArgumentException("Nome de comando obrigatório.");
            }
            if (comandos.putIfAbsent(chave, comando) != null) {
                throw new IllegalArgumentException("Comando duplicado: " + chave);
            }
        }

        String executar(String nome) {
            Comando comando = comandos.get(normalizar(nome));
            return comando == null ? "Comando desconhecido. Digite ajuda." : comando.executar();
        }

        String listarNomes() {
            return String.join(", ", comandos.keySet());
        }
    }

    static final class Historico {
        private final List<String> linhas = new ArrayList<>();

        void registrar(String entrada, String resposta) {
            linhas.add("USUÁRIO: " + entrada.strip());
            linhas.add("BOT: " + resposta);
        }

        String formatar() {
            return linhas.isEmpty() ? "Sem histórico." : String.join(System.lineSeparator(), linhas);
        }

        int totalInteracoes() {
            return linhas.size() / 2;
        }

        void salvar(Path arquivo) throws IOException {
            Files.write(arquivo, linhas, StandardCharsets.UTF_8);
        }
    }

    static final class TutorJavaBot {
        private final RegistroComandos registro = new RegistroComandos();
        private final Historico historico = new Historico();
        private boolean aguardandoQuiz;

        TutorJavaBot() {
            registro.registrar("oi", () -> "Olá! Eu sou o TutorJavaBot.");
            registro.registrar("dica", () -> "Escreva um teste antes de refatorar.");
            registro.registrar("quiz", () -> "Qual componente executa o bytecode Java?");
            registro.registrar("ajuda", () -> "Comandos: " + registro.listarNomes()
                    + ", historico e sair.");
        }

        String processar(String entrada) {
            String comando = normalizar(entrada);
            if (comando.isBlank()) {
                return "Digite uma mensagem.";
            }
            if (comando.equals("historico")) {
                return historico.formatar();
            }

            String resposta;
            if (aguardandoQuiz) {
                resposta = comando.equals("jvm")
                        ? "Correto!"
                        : "Resposta incorreta. A resposta é JVM.";
                aguardandoQuiz = false;
            } else {
                resposta = registro.executar(comando);
                if (comando.equals("quiz")) {
                    aguardandoQuiz = true;
                }
            }

            historico.registrar(entrada, resposta);
            return resposta;
        }

        int totalInteracoes() {
            return historico.totalInteracoes();
        }

        void salvar(Path arquivo) throws IOException {
            historico.salvar(arquivo);
        }
    }

    static String normalizar(String texto) {
        return texto == null ? "" : texto.strip().toLowerCase(Locale.ROOT);
    }

    public static void main(String[] args) {
        TutorJavaBot bot = new TutorJavaBot();

        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println(bot.processar("ajuda"));
            while (true) {
                System.out.print("Você: ");
                String entrada = scanner.nextLine();
                if (normalizar(entrada).equals("sair")) {
                    break;
                }
                System.out.println("Bot: " + bot.processar(entrada));
            }
        }

        try {
            bot.salvar(Path.of("historico.txt"));
            System.out.println("Histórico salvo.");
        } catch (IOException erro) {
            System.out.println("Não foi possível salvar o histórico.");
            System.err.println(erro.getMessage());
        }

        System.out.println("Interações: " + bot.totalInteracoes());
    }
}
