package org.project;

import org.project.location.Location;
import org.project.entity.Entity;
import org.project.entity.enemies.*;
import org.project.entity.players.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class Main {
    private static Scanner scanner = new Scanner(System.in);
    private static Player player;
    private static boolean hasGoblinKey = false;
    private static boolean hasSkeletonKey = false;
    private static boolean hasVampireKey = false;
    private static int currentLocationIndex = 0;
    private static List<Location> locations = new ArrayList<>();
    private static String[] locationNames = {"Forest", "Cemetery", "Crypt", "Ruins"};


    public static void main(String[] args) {
        for (int i = 0; i < locationNames.length; i++) {
            locations.add(new Location(new ArrayList<>(), new ArrayList<>()));
        }

        System.out.println("Welcome to Java Knight");
        System.out.println("Choose your class:");
        System.out.println("1. Knight");
        System.out.println("2. Assassin");
        System.out.println("3. Wizard");
        int choice = readInt("Choice: ", 1, 3);

        switch (choice) {
            case 1:
                player = new Knight("Arthur", 60, 40, 60, 40,
                        12, 24, 8, 20, 10);
                break;
            case 2:
                player = new Assassin("Layla", 45, 55, 45, 55,
                        8, 18, 8, 15, 10);
                break;
            case 3:
                player = new Wizard("Merlin", 70, 50, 70, 50,
                        6, 14, 8, 25, 10);
                break;
        }

        System.out.println(player.getName() + " starts the journey.");
        System.out.println("Collect three keys (Goblin, Skeleton, Vampire) then face the Dragon.\n");

        while (player.isAlive()) {
            System.out.println("\nYou are in " + locationNames[currentLocationIndex] + ".");
            Enemy currentEnemy = spawnRandomEnemyForLocation();
            System.out.println("A " + currentEnemy.getClass().getSimpleName() + " appears!");

            // Menu for the location
            boolean actionDone = false;
            while (!actionDone && player.isAlive()) {
                System.out.println("\nWhat do you want to do?");
                System.out.println("1. Fight the enemy");
                System.out.println("2. Move to another location");
                if (hasGoblinKey && hasSkeletonKey && hasVampireKey) {
                    System.out.println("3. Go to the Castle to fight the Dragon");
                }
                int action = readInt("Choose: ", 1, (hasGoblinKey && hasSkeletonKey && hasVampireKey) ? 3 : 2);

                if (action == 1) {
                    // Fight
                    boolean enemyDefeated = false;
                    while (!enemyDefeated && player.isAlive()) {
                        printStatus(currentEnemy);
                        int combatAction = showCombatMenu();
                        executePlayerAction(combatAction, currentEnemy);
                        if (!currentEnemy.isAlive()) {
                            enemyDefeated = true;
                            break;
                        }
                        if (!player.isAlive()) break;
                        enemyTurn(currentEnemy);
                    }
                    if (!player.isAlive()) {
                        System.out.println("You died. Game over.");
                        return;
                    }
                    // Victory handling
                    handleVictory(currentEnemy);
                    actionDone = true;
                    // Full restore after fight
                    player.fillMana(player.getMaxMP());
                    player.heal(player.getMaxHP() - player.getHp());
                    System.out.println("Your health and mana are fully restored.");
                } else if (action == 2) {
                    // Move to random different location
                    int newIndex = currentLocationIndex;
                    while (newIndex == currentLocationIndex) {
                        newIndex = new Random().nextInt(locations.size());
                    }
                    currentLocationIndex = newIndex;
                    System.out.println("You move to " + locationNames[currentLocationIndex] + ".");
                    actionDone = true; // enemy respawns in new location automatically in next loop iteration
                } else if (action == 3) {
                    // Go to castle
                    fightDragon();
                    if (!player.isAlive()) {
                        System.out.println("You died. Game over.");
                        return;
                    }
                    System.out.println("You defeated the Dragon! The curse is lifted. Victory!");
                    return;
                }
            }
        }
    }

    private static Enemy spawnRandomEnemyForLocation() {
        Random rand = new Random();
        int type = rand.nextInt(3);
        switch (type) {
            case 0: return new Goblin(40, 20, 14);
            case 1: return new Skeleton(50, 20, 12);
            default: return new Vampire(55, 25, 16);
        }
    }

    private static void printStatus(Enemy enemy) {
        System.out.println("\n" + player.getName() + ": " + player.getHp() + "/" + player.getMaxHP() +
                " HP, " + player.getMp() + "/" + player.getMaxMP() + " Mana");
        System.out.println(enemy.getClass().getSimpleName() + ": " + enemy.getHp() + " HP");
    }

    private static int showCombatMenu() {
        System.out.println("\nYour turn:");
        System.out.println("1. Light Attack (0 mana)");
        System.out.println("2. Heavy Attack (8 mana)");
        System.out.println("3. Defend (6 mana)");
        System.out.println("4. Heal (10 mana)");
        System.out.println("5. Special Ability (15 mana)");
        return readInt("Choose: ", 1, 5);
    }

    private static void executePlayerAction(int action, Entity target) {
        switch (action) {
            case 1:
                player.LightAttack(target, 0);
                System.out.println("Light attack performed.");
                break;
            case 2:
                player.HeavyAttack(target, 0);
                System.out.println("Heavy attack performed.");
                break;
            case 3:
                System.out.println(player.defend());
                break;
            case 4:
                player.heal(0);
                System.out.println("Heal attempted.");
                break;
            case 5:
                player.SpecialAbility(target);
                System.out.println("Special ability used.");
                break;
        }
    }

    private static void enemyTurn(Enemy enemy) {
        System.out.println(enemy.getClass().getSimpleName() + "'s turn:");
        Random rand = new Random();
        int dmg = 0;
        if (enemy instanceof Goblin) dmg = ((Goblin) enemy).getAttackDamage();
        else if (enemy instanceof Skeleton) dmg = ((Skeleton) enemy).getAttackDamage();
        else if (enemy instanceof Vampire) dmg = ((Vampire) enemy).getAttackDamage();

        if (rand.nextDouble() < 0.7) {
            enemy.LightAttack(player, dmg);
            System.out.println(enemy.getClass().getSimpleName() + " attacks!");
        } else {
            enemy.SpecialAbility(player);
            System.out.println(enemy.getClass().getSimpleName() + " uses special ability!");
        }
    }

    private static void handleVictory(Enemy enemy) {
        System.out.println(enemy.getClass().getSimpleName() + " defeated!");
        Random rand = new Random();
        int chance = rand.nextInt(100);
        if (enemy instanceof Goblin && !hasGoblinKey && chance < 20) {
            hasGoblinKey = true;
            System.out.println("You obtained the Goblin Key!");
        } else if (enemy instanceof Skeleton && !hasSkeletonKey && chance < 20) {
            hasSkeletonKey = true;
            System.out.println("You obtained the Skeleton Key!");
        } else if (enemy instanceof Vampire && !hasVampireKey && chance < 20) {
            hasVampireKey = true;
            System.out.println("You obtained the Vampire Key!");
        }
        System.out.println("Keys status: Goblin=" + hasGoblinKey + " Skeleton=" + hasSkeletonKey + " Vampire=" + hasVampireKey);
    }

    private static void fightDragon() {
        Dragon dragon = new Dragon(180, 100, 45);
        System.out.println("Dragon appears! Final battle begins.");
        while (player.isAlive() && dragon.isAlive()) {
            printStatus(dragon);
            int action = showCombatMenu();
            executePlayerAction(action, dragon);
            if (!dragon.isAlive()) break;
            if (!player.isAlive()) break;
            System.out.println("Dragon uses fiery breath!");
            dragon.SpecialAbility(player);
            System.out.println("Dragon deals " + dragon.getAttackDamage() * 2 + " damage ignoring defense.");
        }
    }

    private static int readInt(String prompt, int min, int max) {
        int value;
        while (true) {
            System.out.print(prompt);
            if (scanner.hasNextInt()) {
                value = scanner.nextInt();
                if (value >= min && value <= max) return value;
                else System.out.println("Enter number between " + min + " and " + max);
            } else {
                System.out.println("Invalid input. Enter a number.");
                scanner.next();
            }
        }
    }
    }
