package org.project;

import org.project.combat.CombatSystem;
import org.project.entity.Entity;
import org.project.entity.enemies.Dragon;
import org.project.entity.enemies.Goblin;
import org.project.entity.enemies.Skeleton;
import org.project.entity.enemies.Vampire;
import org.project.entity.players.*;
import org.project.location.Location;

import java.util.Random;
import java.util.Scanner;

public class Main {

    private static final Scanner scanner = new Scanner(System.in);
    private static Location currentLocation;

    public static final String RESET = "\u001B[0m";
    public static final String RED = "\u001B[31m";
    public static final String GREEN = "\u001B[32m";
    public static final String YELLOW = "\u001B[33m";
    public static final String BLUE = "\u001B[34m";
    public static final String PURPLE = "\u001B[35m";
    public static final String CYAN = "\u001B[36m";

    public static void main(String[] args) {

        initializeMap();

        while (true) {

            System.out.println(CYAN + "\n===============================" + RESET);
            System.out.println(YELLOW + "        ⚔ JAVA KNIGHT ⚔" + RESET);
            System.out.println(CYAN + "===============================" + RESET);

            System.out.println("1. Start Game");
            System.out.println("2. How To Play");
            System.out.println("3. Exit");

            System.out.print("> ");
            int option = scanner.nextInt();

            switch (option) {
                case 1 -> startGame();
                case 2 -> showHelpMenu();
                case 3 -> {
                    System.out.println(GREEN + "Farewell hero!" + RESET);
                    System.exit(0);
                }
                default -> System.out.println(RED + "Invalid option!" + RESET);
            }
        }
    }


    private static void startGame()
    {

        showIntro();

        System.out.print("Enter your name: ");
        String name = scanner.next();

        System.out.println("\nChoose your class:");
        System.out.println(BLUE + "1. Knight 🛡" + RESET);
        System.out.println(PURPLE + "2. Wizard 🔮" + RESET);
        System.out.println(YELLOW + "3. Assassin 🗡" + RESET);

        int choice = scanner.nextInt();
        Player player;

        switch (choice) {
            case 1 -> player = new Knight(name);
            case 2 -> player = new Wizard(name);
            case 3 -> player = new Assassin(name);
            default -> player = new Knight(name);
        }

        player.resetKeys();
        System.out.println(GREEN + "\nWelcome " + name + " to Javanest!" + RESET);

        currentLocation.enter();
        gameLoop(player);
    }

    private static void gameLoop(Player player)
    {

        Random random = new Random();


        while (player.isAlive())
        {

            showPlayerStatus(player);

            System.out.println(CYAN + "\n===== LOCATION: " + currentLocation.getName() + " =====" + RESET);
            System.out.println("1. Fight Enemy");
            System.out.println("2. Move Location");

            if (player.hasAllKeys() && currentLocation.getName().equals("Vampire Crypt"))
            {
                System.out.println(RED + "3. Enter Dragon Castle 🐉" + RESET);
            }

            System.out.print("> ");
            int option = scanner.nextInt();

            if (option == 1) {
                Entity enemy = currentLocation.spawnEnemy();

                System.out.println(RED + "\nA wild " + enemy.getName() + " appears!" + RESET);

                CombatSystem combat = new CombatSystem();
                combat.startBattle(player, enemy);

                if (!player.isAlive()) {
                    System.out.println(RED + "\nYou have fallen..." + RESET);
                    break;
                }

                tryToDropKey(player, enemy, random);
                recoverPlayer(player);

            } else if (option == 2) {

                moveLocation();

            } else if (option == 3 &&
                    player.hasAllKeys() &&
                    currentLocation.getName().equals("Vampire Crypt")) {

                System.out.println(RED + "\nYou enter the Dragon Castle..." + RESET);

                CombatSystem combat = new CombatSystem();
                combat.startBattle(player, new Dragon());

                if (player.isAlive()) {
                    System.out.println(GREEN + "\n🏆 YOU SAVED JAVANEST!" + RESET);
                } else {
                    System.out.println(RED + "\nThe Dragon has defeated you..." + RESET);
                }

                showProjectFeatures();
                break;

            } else {
                System.out.println(RED + "Invalid option!" + RESET);
            }
        }
    }

    private static void showPlayerStatus(Player player) {

        System.out.println(YELLOW + "\n===== PLAYER STATUS =====" + RESET);

        printBar("HP ", player.getHP(), player.getMaxHP(), RED);
        printBar("MP ", player.getMP(), player.getMaxMP(), BLUE);
        System.out.println("XP: " + player.getXP());
    }

    private static void printBar(String label, int value, int max, String color)
    {

        int totalBars = 20;
        int filled = (int)((double)value / max * totalBars);

        StringBuilder bar = new StringBuilder();

        for (int i = 0; i < filled; i++) bar.append("█");
        for (int i = filled; i < totalBars; i++) bar.append("░");

        System.out.println(label + " " + color + bar + RESET + " " + value + "/" + max);
    }

    private static void moveLocation()
    {

        System.out.println(YELLOW + "\nWhere do you want to go?" + RESET);

        int index = 1;
        for (Location loc : currentLocation.getConnectedLocations())
        {
            System.out.println(index + ". " + loc.getName());
            index++;
        }

        System.out.print("> ");
        int choice = scanner.nextInt();

        if (choice < 1 || choice > currentLocation.getConnectedLocations().size())
        {
            System.out.println(RED + "Invalid location!" + RESET);
            return;
        }

        currentLocation = currentLocation.getConnectedLocations().get(choice - 1);
        currentLocation.enter();
    }

    private static void tryToDropKey(Player player, Entity enemy, Random random)
    {

        int chance = random.nextInt(100) + 1;

        if (chance <= 20)
        {

            if (enemy instanceof Goblin && !player.hasGoblinKey())
            {
                player.obtainGoblinKey();
                System.out.println(YELLOW + "You obtained the Goblin Key!" + RESET);
            } else if (enemy instanceof Skeleton && !player.hasSkeletonKey()) {
                player.obtainSkeletonKey();
                System.out.println(YELLOW + "You obtained the Skeleton Key!" + RESET);
            } else if (enemy instanceof Vampire && !player.hasVampireKey()) {
                player.obtainVampireKey();
                System.out.println(YELLOW + "You obtained the Vampire Key!" + RESET);
            }
        }
    }

    private static void recoverPlayer(Player player)
    {
        player.setHealth(player.getMaxHP());
        player.setMana(player.getMaxMP());
        System.out.println(GREEN + "You recovered your HP and Mana." + RESET);
    }

    private static void showIntro()
    {
        System.out.println(PURPLE + "\n====================================" + RESET);
        System.out.println(YELLOW + "        LEGEND OF JAVANEST" + RESET);
        System.out.println(PURPLE + "====================================" + RESET);
        System.out.println("Defeat enemies, collect keys,");
        System.out.println("and face the mighty Dragon!");
    }

    private static void showHelpMenu()
    {
        System.out.println(YELLOW + "\nHOW TO PLAY:" + RESET);
        System.out.println("- Fight enemies to gain XP.");
        System.out.println("- Collect 3 keys.");
        System.out.println("- Unlock Dragon Castle.");
        System.out.println("- Defeat the Dragon to win.");
    }

    private static void showProjectFeatures()
    {

        System.out.println(CYAN + "\n====================================" + RESET);
        System.out.println(YELLOW + "        PROJECT FEATURES" + RESET);
        System.out.println(CYAN + "====================================" + RESET);

        System.out.println(GREEN + "✔ Multiple Player Classes" + RESET);
        System.out.println(GREEN + "✔ Location System" + RESET);
        System.out.println(GREEN + "✔ Key Collection System" + RESET);
        System.out.println(GREEN + "✔ Combat System" + RESET);
        System.out.println(GREEN + "✔ Final Boss Battle" + RESET);
    }

    private static void initializeMap()
    {

        Location forest = new Location(
                "Forest",
                "A dark forest full of goblins.",
                1
        );

        Location graveyard = new Location(
                "Graveyard",
                "An abandoned graveyard with skeletons.",
                2
        );

        Location vampireCrypt = new Location(
                "Vampire Crypt",
                "A cursed crypt where vampires sleep.",
                3
        );

        Location dragonCastle = new Location(
                "Dragon Castle",
                "The castle of the ancient dragon.",
                4
        );

        forest.connectLocation(graveyard);
        graveyard.connectLocation(forest);

        graveyard.connectLocation(vampireCrypt);
        vampireCrypt.connectLocation(graveyard);

        vampireCrypt.connectLocation(dragonCastle);

        currentLocation = forest;
    }
}