package org.project.main;

import org.project.entity.Entity;
import org.project.entity.players.Knight;
import org.project.entity.enemies.*; // import همه دشمنان
import org.project.location.Location; // import کلاس Location

import java.util.*;

public class Main
{
    private static final Scanner scanner = new Scanner(System.in);
    private static final Random random = new Random();
    private static Knight player;
    private static List<Location> gameLocations = new ArrayList<>();
    private static Location currentLocation;
    private static Set<String> keys = new HashSet<>();
    private static boolean castleUnlocked = false;

    public static void main(String[] args)
    {
        System.out.println("Welcome to Java Knight RPG!");
        System.out.print("Enter your hero's name: ");
        String name = scanner.nextLine();
        player = new Knight(name);

        initializeLocations();
        if (!gameLocations.isEmpty())
        {
            currentLocation = gameLocations.get(0);
            System.out.println("Your adventure begins in the " + currentLocation.getName() + "!");
        }
        else
        {
            System.out.println("Error: No locations initialized. Exiting.");
            System.exit(1);
        }

        gameLoop();
    }

    private static void initializeLocations()
    {
        Location forest = new Location(new ArrayList<>(), new ArrayList<>());
        forest.setName("Dark Forest");

        Location cave = new Location(new ArrayList<>(), new ArrayList<>());
        cave.setName("Mysterious Cave");

        Location castle = new Location(new ArrayList<>(), new ArrayList<>());
        castle.setName("Dragon's Castle");

        forest.addEnemy(new Goblin());
        forest.addEnemy(new Skeleton());

        cave.addEnemy(new Vampire());
        cave.addEnemy(new Skeleton());

        forest.addAdjacentLocation(cave);
        cave.addAdjacentLocation(forest);
        cave.addAdjacentLocation(castle);
        castle.addAdjacentLocation(cave);

        gameLocations.add(forest);
        gameLocations.add(cave);
        gameLocations.add(castle);
    }

    private static void gameLoop()
    {
        while (true)
        {
            if (currentLocation != null && currentLocation.hasLivingEnemies())
            {
                System.out.println("\n\u001B[33mEnemies detected in " + currentLocation.getName() + "!\u001B[0m");
            }

            System.out.println("\n====== Main Menu ======");
            if (currentLocation != null)
            {
                System.out.println("Current Location: " + currentLocation.getName());
            }
            else
            {
                System.out.println("Current Location: Unknown");
            }
            System.out.println("1. Fight enemy");
            System.out.println("2. Move to another location");
            if (castleUnlocked)
            {
                System.out.println("3. Enter the Castle (Final Boss)");
            }
            else
            {
                System.out.println("3. Enter the Castle (Locked - Collect all keys!)");
            }
            System.out.println("4. Show player info");
            System.out.println("5. Exit game");
            System.out.print("Choose an option: ");

            int choice = readInt(1, 5);
            switch (choice)
            {
                case 1 ->
                {
                    if (currentLocation != null && currentLocation.hasLivingEnemies())
                    {
                        fightEnemy();
                    }
                    else
                    {
                        System.out.println("No enemies here to fight.");
                    }
                }
                case 2 -> moveLocation();
                case 3 ->
                {
                    if (currentLocation != null && currentLocation.getName().equals("Dragon's Castle") && castleUnlocked)
                    {
                        fightBoss();
                    }
                    else if (castleUnlocked)
                    {
                        System.out.println("You must be at the Castle entrance to enter.");
                    }
                    else
                    {
                        System.out.println("You need to collect all keys before entering the Castle.");
                    }
                }
                case 4 -> showPlayerInfo();
                case 5 ->
                {
                    System.out.println("Thanks for playing! Goodbye.");
                    scanner.close();
                    System.exit(0);
                }
            }
        }
    }

    private static void fightEnemy()
    {
        if (currentLocation == null || !currentLocation.hasLivingEnemies())
        {
            System.out.println("No enemies here to fight.");
            return;
        }

        Enemy enemy = null;
        for (Enemy e : currentLocation.getEnemies())
        {
            if (e.isAlive())
            {
                enemy = e;
                break;
            }
        }

        if (enemy == null)
        {
            System.out.println("No living enemies found.");
            return;
        }

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

        boolean playerTurn = true;
        while (player.isAlive() && enemy.isAlive())
        {
            printStatus(player, enemy);
            if (playerTurn)
            {
                System.out.println("\nYour turn! Choose action:");
                System.out.println("1. Attack");
                System.out.println("2. Defend");
                System.out.print("Option: ");
                int act = readInt(1, 2);
                if (act == 1)
                {
                    player.attack(enemy);
                }
                else
                {
                    player.defend();
                }
            }
            else
            {
                enemy.attack(player);
            }
            playerTurn = !playerTurn;
        }

        if (!player.isAlive())
        {
            System.out.println("\u001B[31mYou died! Game over.\u001B[0m");
            scanner.close();
            System.exit(0);
        }
        else
        {
            System.out.println("\u001B[32mYou defeated " + enemy.getName() + "!\u001B[0m");

            tryDropKey(enemy);

            int xpGain = getXPGain(enemy);
            player.addXP(xpGain);
            player.checkLevelUp();

            player.setHP(player.getMaxHP());
            player.setMP(player.getMaxMP());
            System.out.println("\u001B[36mYour HP and MP are fully restored.\u001B[0m");

            currentLocation.getEnemies().remove(enemy);
        }
    }

    private static void moveLocation()
    {
        if (currentLocation == null)
        {
            System.out.println("You are in an unknown location.");
            return;
        }

        ArrayList<Location> adjacent = currentLocation.getLocations();
        if (adjacent == null || adjacent.isEmpty())
        {
            System.out.println("There are no other locations connected to this place.");
            return;
        }

        System.out.println("\nAvailable locations to move:");
        for (int i = 0; i < adjacent.size(); i++)
        {
            System.out.println((i + 1) + ". " + adjacent.get(i).getName());
        }
        System.out.print("Choose a location to move to (or 0 to cancel): ");
        int choice = readInt(0, adjacent.size());
        if (choice == 0)
        {
            System.out.println("Movement cancelled.");
            return;
        }

        currentLocation = adjacent.get(choice - 1);
        System.out.println("You moved to " + currentLocation.getName());

        if (currentLocation.hasLivingEnemies())
        {
            System.out.println("\u001B[33mWatch out! There are enemies here.\u001B[0m");
        }
    }

    private static void fightBoss()
    {
        if (currentLocation == null || !currentLocation.getName().equals("Dragon's Castle"))
        {
            System.out.println("You must be in the Dragon's Castle to fight the boss.");
            return;
        }

        Dragon dragon = new Dragon();
        System.out.println("\nYou enter the Dragon's Lair!");

        boolean playerTurn = true;
        while (player.isAlive() && dragon.isAlive())
        {
            printStatus(player, dragon);
            if (playerTurn)
            {
                System.out.println("\nYour turn! Choose action:");
                System.out.println("1. Attack");
                System.out.println("2. Defend");
                System.out.print("Option: ");
                int act = readInt(1, 2);
                if (act == 1)
                {
                    player.attack(dragon);
                }
                else
                {
                    player.defend();
                }
            }
            else
            {
                dragon.attack(player);
            }
            playerTurn = !playerTurn;
        }

        if (player.isAlive())
        {
            System.out.println("\u001B[32mCongratulations! You defeated the Dragon and won the game!\u001B[0m");
            scanner.close();
            System.exit(0);
        }
        else
        {
            System.out.println("\u001B[31mYou died fighting the Dragon. Game over.\u001B[0m");
            scanner.close();
            System.exit(0);
        }
    }

    private static void showPlayerInfo()
    {
        System.out.println("\n--- Player Info ---");
        System.out.println("Name: " + player.getName());
        System.out.println("Level: " + player.level);
        System.out.println("XP: " + player.xp + " / " + player.xpToNextLevel);
        System.out.println("HP: " + player.getHP() + "/" + player.getMaxHP());
        System.out.println("MP: " + player.getMP() + "/" + player.getMaxMP());
        System.out.println("Keys collected: " + keys);
    }

    private static int readInt(int min, int max)
    {
        int input;
        while (true)
        {
            try
            {
                input = Integer.parseInt(scanner.nextLine());
                if (input < min || input > max)
                {
                    throw new NumberFormatException("Input out of bounds.");
                }
                break;
            }
            catch (NumberFormatException e)
            {
                System.out.print("Invalid input. Please enter a number between " + min + " and " + max + ": ");
            }
        }
        return input;
    }

    private static void tryDropKey(Entity enemy)
    {
        double dropChance = 0.20;
        String enemyName = enemy.getName();

        if (keys.contains(enemyName + " Key")) {return;}

        if (random.nextDouble() < dropChance)
        {
            keys.add(enemyName + " Key");
            System.out.println("\u001B[36mYou obtained the " + enemyName + " Key!\u001B[0m");
        }

        if (keys.contains("Goblin Key") && keys.contains("Skeleton Key") && keys.contains("Vampire Key"))
        {
            castleUnlocked = true;
            System.out.println("\u001B[35mAll keys collected! The Castle is now unlocked!\u001B[0m");
        }
    }

    private static int getXPGain(Entity enemy)
    {
        return switch (enemy.getName())
        {
            case "Goblin" -> 50;
            case "Skeleton" -> 40;
            case "Vampire" -> 60;
            case "Dragon" -> 500;
            default -> 50;
        };
    }

    private static void printStatus(Entity player, Entity enemy)
    {
        System.out.println("\n[player HP: " + player.getHP() + " / " + player.getMaxHP() +
                " | MP: " + player.getMP() + " / " + player.getMaxMP() + "]");
        System.out.println("[enemy HP: " + enemy.getHP() + " / " + enemy.getMaxHP() + "]");
    }
}