package com.openosrs.client.api;

import com.openosrs.client.core.ClientCore;
import com.openosrs.client.core.bridge.BridgeAdapter;
import com.openosrs.client.api.types.Item;
import com.openosrs.client.api.types.NPC;
import com.openosrs.client.api.types.Position;
import com.openosrs.client.api.types.Skill;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.concurrent.CompletableFuture;

/**
 * CombatAPI - Handles combat-related actions and state.
 *
 * This API module provides methods for:
 * - Combat actions (attacking, eating, drinking potions)
 * - Combat state monitoring
 * - Health and prayer management
 * - Combat calculations and utilities
 */
public class CombatAPI {
    private static final Logger logger = LoggerFactory.getLogger(CombatAPI.class);

    private final ClientCore clientCore;
    private final BridgeAdapter bridgeAdapter;

    // Common food item IDs (for auto-eating)
    private static final int[] FOOD_IDS = {
        385,   // Shark
        379,   // Lobster
        373,   // Swordfish
        365,   // Bass
        361,   // Tuna
        329,   // Salmon
        315,   // Shrimps
        7946,  // Monkfish
        3144,  // Karambwan
        6297,  // Anglerfish
        385,   // Shark
        12625, // Saradomin brew
    };

    // Common potion IDs
    private static final int[] COMBAT_POTIONS = {
        2428,  // Attack potion(4)
        113,   // Strength potion(4)
        2440,  // Super attack(4)
        2442,  // Super strength(4)
        2436,  // Super defence(4)
        2444,  // Ranging potion(4)
        3024,  // Super energy(4)
        3016,  // Energy potion(4)
        2434,  // Prayer potion(4)
        12625, // Saradomin brew(4)
        12631, // Super restore(4)
    };

    public CombatAPI(ClientCore clientCore, BridgeAdapter bridgeAdapter) {
        this.clientCore = clientCore;
        this.bridgeAdapter = bridgeAdapter;
    }

    /**
     * Attack an NPC.
     */
    public CompletableFuture<Boolean> attackNPC(NPC npc) {
        if (npc == null) {
            return CompletableFuture.completedFuture(false);
        }

        logger.debug("Attacking NPC: {} (ID: {})", npc.getName(), npc.getId());

        return CompletableFuture.supplyAsync(() -> {
            try {
                // Check if NPC is attackable
                if (!npc.isInteractable()) {
                    logger.warn("NPC {} is not attackable", npc.getName());
                    return false;
                }

                Position playerPos = bridgeAdapter.getPlayerPosition();
                if (playerPos == null) {
                    logger.warn("Cannot attack - player position unknown");
                    return false;
                }

                double distance = npc.getPosition().distanceTo(playerPos);
                if (distance > 10) {
                    logger.warn("NPC too far away for attack: {} tiles", distance);
                    return false;
                }

                // Check if already in combat
                if (clientCore.getPlayerState().isInCombat()) {
                    logger.debug("Already in combat, switching targets");
                }

                // TODO: Send attack packet to server
                // TODO: Update combat state

                // Simulate attack time
                Thread.sleep(600); // 1 game tick

                logger.debug("Attack initiated on NPC: {}", npc.getName());
                return true;

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Attack interrupted");
                return false;
            } catch (Exception e) {
                logger.error("Error during attack", e);
                return false;
            }
        });
    }

    /**
     * Eat food from inventory (automatically finds food).
     */
    public CompletableFuture<Boolean> eatFood() {
        logger.debug("Attempting to eat food");

        return CompletableFuture.supplyAsync(() -> {
            try {
                // Find food in inventory
                Item[] inventory = bridgeAdapter.getInventory();

                for (int slot = 0; slot < inventory.length; slot++) {
                    Item item = inventory[slot];
                    if (item != null && !item.isEmpty() && isFood(item.getId())) {
                        logger.debug("Eating food: {}", item.getName());

                        // TODO: Send eat packet to server
                        // TODO: Update player health

                        // Simulate eating time
                        Thread.sleep(1800); // 3 game ticks

                        logger.debug("Food consumed: {}", item.getName());
                        return true;
                    }
                }

                logger.warn("No food found in inventory");
                return false;

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Eating interrupted");
                return false;
            } catch (Exception e) {
                logger.error("Error eating food", e);
                return false;
            }
        });
    }

    /**
     * Drink a specific potion.
     */
    public CompletableFuture<Boolean> drinkPotion(int itemId) {
        logger.debug("Attempting to drink potion: {}", itemId);

        return CompletableFuture.supplyAsync(() -> {
            try {
                // Find potion in inventory
                Item[] inventory = bridgeAdapter.getInventory();
                Item potion = null;
                int foundSlot = -1;
                
                for (int slot = 0; slot < inventory.length; slot++) {
                    Item item = inventory[slot];
                    if (item != null && !item.isEmpty() && item.getId() == itemId) {
                        potion = item;
                        foundSlot = slot;
                        break;
                    }
                }
                
                if (potion == null) {
                    logger.warn("Potion {} not found in inventory", itemId);
                    return false;
                }
                logger.debug("Drinking potion: {}", potion.getName());

                // TODO: Send drink packet to server
                // TODO: Update player stats based on potion effect

                // Simulate drinking time
                Thread.sleep(1800); // 3 game ticks

                logger.debug("Potion consumed: {}", potion.getName());
                return true;

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Drinking interrupted");
                return false;
            } catch (Exception e) {
                logger.error("Error drinking potion", e);
                return false;
            }
        });
    }

    /**
     * Get current combat target.
     */
    public NPC getCombatTarget() {
        // TODO: Track current combat target
        // For now, return null as we don't have combat state tracking yet
        return null;
    }

    /**
     * Check if the player should eat (low health).
     */
    public boolean shouldEat() {
        int currentHp = bridgeAdapter.getSkillLevel(Skill.HITPOINTS);
        int maxHp = bridgeAdapter.getSkillRealLevel(Skill.HITPOINTS);

        double healthPercentage = (double) currentHp / maxHp;
        return healthPercentage < 0.6; // Eat when below 60% health
    }

    /**
     * Check if the player should drink a prayer potion.
     */
    public boolean shouldDrinkPrayerPotion() {
        int currentPrayer = bridgeAdapter.getSkillLevel(Skill.PRAYER);
        int maxPrayer = bridgeAdapter.getSkillRealLevel(Skill.PRAYER);

        double prayerPercentage = (double) currentPrayer / maxPrayer;
        return prayerPercentage < 0.25; // Drink when below 25% prayer
    }

    /**
     * Automatically handle combat (eat food, drink potions if needed).
     */
    public CompletableFuture<Boolean> autoManageCombat() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                boolean actionTaken = false;

                // Check if we need to eat
                if (shouldEat()) {
                    logger.debug("Health low, attempting to eat");
                    if (eatFood().get()) {
                        actionTaken = true;
                    }
                }

                // Check if we need prayer
                if (shouldDrinkPrayerPotion()) {
                    logger.debug("Prayer low, attempting to drink prayer potion");
                    // Try to drink prayer potion (4)
                    if (drinkPotion(2434).get()) {
                        actionTaken = true;
                    }
                }

                return actionTaken;

            } catch (Exception e) {
                logger.error("Error during auto combat management", e);
                return false;
            }
        });
    }

    /**
     * Check if an item ID is food.
     */
    private boolean isFood(int itemId) {
        return Arrays.stream(FOOD_IDS).anyMatch(foodId -> foodId == itemId);
    }

    /**
     * Check if an item ID is a combat potion.
     */
    private boolean isCombatPotion(int itemId) {
        return Arrays.stream(COMBAT_POTIONS).anyMatch(potionId -> potionId == itemId);
    }

    /**
     * Calculate the player's max hit (simplified).
     */
    public int calculateMaxHit() {
        // TODO: Implement proper max hit calculation
        // This would need to consider strength level, equipment, potions, etc.
        int strLevel = bridgeAdapter.getSkillLevel(Skill.STRENGTH);
        return Math.max(1, strLevel / 10); // Very simplified calculation
    }

    /**
     * Calculate combat effectiveness against an NPC.
     */
    public double calculateCombatEffectiveness(NPC npc) {
        if (npc == null) {
            return 0.0;
        }

        // TODO: Implement proper effectiveness calculation
        // This would consider combat levels, equipment, NPC defence, etc.
        int playerCombatLevel = clientCore.getPlayerState().getCombatLevel();
        int npcCombatLevel = npc.getCombatLevel();

        if (npcCombatLevel == 0) {
            return 1.0; // Non-combat NPC
        }

        return Math.min(1.0, (double) playerCombatLevel / npcCombatLevel);
    }

    /**
     * Check if it's safe to engage in combat.
     */
    public boolean isSafeToCombat() {
        // Check health
        if (shouldEat() && !hasFood()) {
            logger.warn("Not safe to combat - low health and no food");
            return false;
        }

        // Check if already in dangerous combat
        int currentHp = bridgeAdapter.getSkillLevel(Skill.HITPOINTS);
        if (currentHp <= 20 && clientCore.getPlayerState().isInCombat()) {
            logger.warn("Not safe to combat - critical health in combat");
            return false;
        }

        return true;
    }

    /**
     * Check if the player has food in inventory.
     */
    public boolean hasFood() {
        Item[] inventory = bridgeAdapter.getInventory();

        for (Item item : inventory) {
            if (item != null && !item.isEmpty() && isFood(item.getId())) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get the amount of food in inventory.
     */
    public int getFoodCount() {
        Item[] inventory = bridgeAdapter.getInventory();
        int count = 0;

        for (Item item : inventory) {
            if (item != null && !item.isEmpty() && isFood(item.getId())) {
                count += item.getQuantity();
            }
        }

        return count;
    }
}
