import { 
    world, 
    system, 
    Player, 
    EntityComponentTypes
    // EntityDamageCause はエラー回避のため削除
} from "@minecraft/server";

// ==========================================
// 設定 (Config)
// ==========================================
const CONFIG = {
    MAX_THIRST: 100,
    DECAY_AMOUNT: 1,
    DECAY_INTERVAL: 40, // 2秒
    
    // 直飲みチェックの間隔 (Tick)
    DRINK_CHECK_INTERVAL: 5,
    
    // 連続飲み防止のクールダウン (Tick)
    DRINK_COOLDOWN: 30,

    RECOVER: {
        WATER_BOTTLE: 30,
        MILK_BUCKET: 20,    // バランス調整済み
        MELON_SLICE: 10,
        FRUIT: 15,          // 一般的な果物
        BERRIES: 5,         // ベリー類
        STEW: 25,           // シチュー・スープ類
        PURIFIED_WATER: 50, // 浄化した水
        DIRECT_DRINK: 15    // 直飲み
    },
    
    POISON_CHANCE: 0.3,       // 通常の食中毒 (30%)
    HEAVY_POISON_CHANCE: 0.03 // 重篤な症状 (3%)
};

// 難易度定数
const DIFFICULTY = {
    EASY: 0,    // 減らない（100%固定）
    NORMAL: 1,  // x0.5
    HARD: 2,    // x1.0
    EXTREME: 3  // x1.5
};

// プレイヤーごとのクールダウン管理 (最後に飲んだTickを記録)
const lastDrinkTicks = new Map();

// ==========================================
// コマンドシステム (難易度変更)
// ==========================================
world.beforeEvents.chatSend.subscribe((event) => {
    const message = event.message;
    const player = event.sender;

    if (!message.startsWith("!hydration")) return;

    event.cancel = true;

    const args = message.split(" ");

    if (args.length < 2) {
        player.sendMessage("§c[Hydration] Usage: !hydration <easy|normal|hard|extreme>");
        const currentDiff = getDifficultyName(getDifficulty());
        player.sendMessage(`§7Current Difficulty: ${currentDiff}`);
        return;
    }

    const modeStr = args[1].toLowerCase();
    let newMode = -1;
    let modeName = "";

    switch (modeStr) {
        case "easy":
        case "0":
            newMode = DIFFICULTY.EASY;
            modeName = "§aEasy (Fixed 100%)";
            break;
        case "normal":
        case "1":
            newMode = DIFFICULTY.NORMAL;
            modeName = "§eNormal (0.5x Speed)";
            break;
        case "hard":
        case "2":
            newMode = DIFFICULTY.HARD;
            modeName = "§cHard (Standard)";
            break;
        case "extreme":
        case "3":
            newMode = DIFFICULTY.EXTREME;
            modeName = "§4Extreme (1.5x Speed)";
            break;
        default:
            player.sendMessage("§c[Hydration] Invalid difficulty. Use: easy, normal, hard, extreme");
            return;
    }

    world.setDynamicProperty("hydration:difficulty", newMode);
    world.sendMessage(`§b[Hydration] §fDifficulty set to ${modeName}§f.`);
});

/**
 * 現在の難易度設定を取得
 */
function getDifficulty() {
    const diff = world.getDynamicProperty("hydration:difficulty");
    return typeof diff === "number" ? diff : DIFFICULTY.NORMAL;
}

/**
 * 難易度名を取得
 */
function getDifficultyName(diff) {
    switch (diff) {
        case DIFFICULTY.EASY: return "Easy";
        case DIFFICULTY.NORMAL: return "Normal";
        case DIFFICULTY.HARD: return "Hard";
        case DIFFICULTY.EXTREME: return "Extreme";
        default: return "Unknown";
    }
}


// ==========================================
// メインループ: 水分減少とUI表示
// ==========================================

system.runInterval(() => {
    const difficulty = getDifficulty();

    for (const player of world.getAllPlayers()) {
        // 各関数内で個別にゲームモード判定を行うように変更し、
        // 処理漏れを防ぐ
        updateThirst(player, difficulty);
        displayThirstUI(player, difficulty);
        checkThirstPenalty(player);
    }
}, CONFIG.DECAY_INTERVAL); 

// ==========================================
// サブループ: 直飲み判定
// ==========================================
system.runInterval(() => {
    for (const player of world.getAllPlayers()) {
        // 直飲みチェック内でもゲームモード判定を行う
        checkDirectDrink(player);
    }
}, CONFIG.DRINK_CHECK_INTERVAL);


/**
 * プレイヤーの水分を減少させる処理
 */
function updateThirst(player, difficulty) {
    const gamemode = player.getGameMode();

    // クリエイティブ・スペクテイター、またはEasyモードなら
    // 強制的に100%に固定して終了（減少させない）
    if (gamemode === "creative" || gamemode === "spectator" || difficulty === DIFFICULTY.EASY) {
        setThirst(player, CONFIG.MAX_THIRST);
        return;
    }

    let decay = CONFIG.DECAY_AMOUNT;

    if (difficulty === DIFFICULTY.NORMAL) {
        decay *= 0.5;
    } else if (difficulty === DIFFICULTY.HARD) {
        decay *= 1.0;
    } else if (difficulty === DIFFICULTY.EXTREME) {
        decay *= 1.5;
    }

    if (player.isSprinting) {
        decay *= 2;
    }

    if (player.dimension.id === "minecraft:nether") {
        decay *= 1.5;
    }
    
    let currentThirst = getThirst(player);
    currentThirst = Math.max(0, currentThirst - decay);
    setThirst(player, currentThirst);
}

/**
 * 水分量を画面(Actionbar)に表示
 */
function displayThirstUI(player, difficulty) {
    const gamemode = player.getGameMode();

    // クリエイティブ・スペクテイターなら表示を消す
    if (gamemode === "creative" || gamemode === "spectator") {
        // 空白文字を送ることで、以前の表示を確実に上書きして消去する
        player.onScreenDisplay.setActionBar(" ");
        return;
    }

    const thirst = getThirst(player);
    const percentage = Math.floor((thirst / CONFIG.MAX_THIRST) * 100);
    
    const iconCount = 10;
    const fillCount = Math.ceil((thirst / CONFIG.MAX_THIRST) * iconCount);
    
    // 直飲みのクールダウン中か判定
    const currentTick = system.currentTick;
    const lastDrink = lastDrinkTicks.get(player.id);
    let isCooldown = false;

    if (lastDrink !== undefined) {
        const diff = currentTick - lastDrink;
        if (diff >= 0 && diff < CONFIG.DRINK_COOLDOWN) {
            isCooldown = true;
        }
    }

    // クールダウン中は色をグレーにする
    let barColor = isCooldown ? "§7" : "§b"; 
    let emptyColor = "§8";

    let bar = barColor;
    for (let i = 0; i < iconCount; i++) {
        if (i < fillCount) {
            bar += "■";
        } else {
            bar += emptyColor + "■";
        }
    }

    let statusLabel = "";
    if (difficulty === DIFFICULTY.EASY) {
        statusLabel = " §a(Easy)";
    } else if (isCooldown) {
        statusLabel = " §6⌛"; // クールダウン中は時計アイコン
    }

    player.onScreenDisplay.setActionBar(`Hydration: ${bar} §f(${percentage}%)${statusLabel}`);
}

/**
 * 枯渇時のペナルティ処理
 */
function checkThirstPenalty(player) {
    const gamemode = player.getGameMode();
    // クリエイティブ等はペナルティなし
    if (gamemode === "creative" || gamemode === "spectator") return;

    if (getDifficulty() === DIFFICULTY.EASY) return;

    const thirst = getThirst(player);

    if (thirst <= 0) {
        const duration = 200;
        
        player.addEffect("slowness", duration, { amplifier: 1, showParticles: false });
        player.addEffect("nausea", duration, { amplifier: 0, showParticles: false });

        player.applyDamage(1); 
    }
}

// ==========================================
// 飲水システム (アイテム使用)
// ==========================================

world.afterEvents.itemCompleteUse.subscribe((event) => {
    const player = event.source;
    if (!(player instanceof Player)) return;

    const itemStack = event.itemStack;
    if (!itemStack) return;
    
    const itemId = itemStack.typeId;
    
    // 1. ポーション類 (水入り瓶か、その他の効果付きか判定)
    if (itemId === "minecraft:potion") {
        addThirst(player, CONFIG.RECOVER.WATER_BOTTLE);
        // Script APIで水入り瓶のみを正確に特定するのが難しいため、
        // ユーザー体験を優先し、ポーション類は一律「安全」とする（回復のみ）。
    } 
    // 2. 牛乳
    else if (itemId === "minecraft:milk_bucket") {
        addThirst(player, CONFIG.RECOVER.MILK_BUCKET);
    } 
    // 3. スイカ
    else if (itemId === "minecraft:melon_slice") {
        addThirst(player, CONFIG.RECOVER.MELON_SLICE);
    } 
    // 4. 果物類
    else if (
        itemId === "minecraft:apple" ||
        itemId === "minecraft:golden_apple" ||
        itemId === "minecraft:enchanted_golden_apple" ||
        itemId === "minecraft:chorus_fruit"
    ) {
        addThirst(player, CONFIG.RECOVER.FRUIT);
    }
    // 5. ベリー類
    else if (
        itemId === "minecraft:sweet_berries" ||
        itemId === "minecraft:glow_berries"
    ) {
        addThirst(player, CONFIG.RECOVER.BERRIES);
    }
    // 6. シチュー・スープ類
    else if (
        itemId === "minecraft:mushroom_stew" ||
        itemId === "minecraft:beetroot_soup" ||
        itemId === "minecraft:rabbit_stew" ||
        itemId === "minecraft:suspicious_stew"
    ) {
        addThirst(player, CONFIG.RECOVER.STEW);
    }
    // 7. きれいな水 (カスタムアイテム)
    else if (itemId === "hydration:purified_water") {
        addThirst(player, CONFIG.RECOVER.PURIFIED_WATER);
        player.sendMessage("§aFresh water! (Purified)");
    }
});

// ==========================================
// プレイヤー退出時の処理 (データクリーンアップ)
// ==========================================
world.afterEvents.playerLeave.subscribe((event) => {
    if (event.playerId) {
        lastDrinkTicks.delete(event.playerId);
    }
});

// ==========================================
// リスポーン処理 (死亡時リセット)
// ==========================================
world.afterEvents.playerSpawn.subscribe((event) => {
    const player = event.player;
    if (!event.initialSpawn) {
        setThirst(player, CONFIG.MAX_THIRST);
    }
});

// ==========================================
// 直飲みシステム (水中スニーク版)
// ==========================================

function checkDirectDrink(player) {
    const gamemode = player.getGameMode();
    // クリエイティブ等は直飲み判定を行わない
    if (gamemode === "creative" || gamemode === "spectator") return;

    if (!player.isSneaking) return;

    const currentTick = system.currentTick;
    const lastDrink = lastDrinkTicks.get(player.id);

    // クールダウンチェック
    if (lastDrink !== undefined) {
        const diff = currentTick - lastDrink;
        if (diff >= 0 && diff < CONFIG.DRINK_COOLDOWN) {
            return;
        }
    }

    const inventory = player.getComponent(EntityComponentTypes.Inventory);
    const container = inventory.container;
    const mainHandItem = container.getItem(player.selectedSlotIndex);

    if (mainHandItem) return;

    let isWater = false;
    const dimension = player.dimension;

    // 1. 視線判定 (Raycast) - 岸から飲む用
    const raycast = player.getBlockFromViewDirection({ maxDistance: 5.0 });
    if (raycast) {
        const block = raycast.block;
        if (block && (block.typeId.includes("water") || block.typeId === "minecraft:water_cauldron")) {
            isWater = true;
        }
    }

    // 2. 位置判定 (Body check) - 水中用
    if (!isWater) {
        const loc = player.location;
        const checkPoints = [
            loc, // 足元
            { x: loc.x, y: loc.y + 0.2, z: loc.z }, // 足首
            { x: loc.x, y: loc.y + 0.5, z: loc.z }, // 腰
            player.getHeadLocation() // 頭
        ];

        for (const point of checkPoints) {
            const block = dimension.getBlock(point);
            if (block && (block.typeId.includes("water") || block.typeId === "minecraft:water_cauldron")) {
                isWater = true;
                break;
            }
        }
    }

    // 水が見つかった場合の処理
    if (isWater) {
        // アイテムチェック（素手かどうかの確認）
        const inventory = player.getComponent(EntityComponentTypes.Inventory);
        const container = inventory.container;
        const mainHandItem = container.getItem(player.selectedSlotIndex);

        if (mainHandItem) {
            // 手にアイテムを持っている場合は飲めない
            player.onScreenDisplay.setActionBar("§c[!] 手がふさがっています (素手で飲んでください)");
            return;
        }

        executeDirectDrink(player);
        lastDrinkTicks.set(player.id, currentTick);
    }
}

function executeDirectDrink(player) {
    player.dimension.playSound("random.drink", player.location);
    addThirst(player, CONFIG.RECOVER.DIRECT_DRINK);
    applyDirtyWaterPenalty(player); // 直飲みは必ずリスクあり
    player.sendMessage("§bDrank river water...");
}


// ==========================================
// ユーティリティ関数
// ==========================================

function applyDirtyWaterPenalty(player) {
    if (getDifficulty() === DIFFICULTY.EASY) return;

    const rand = Math.random();

    if (rand < CONFIG.HEAVY_POISON_CHANCE) {
        player.addEffect("poison", 200, { amplifier: 0 }); 
        player.addEffect("nausea", 300, { amplifier: 1 });
        player.sendMessage("§c§lUgh...! Intense nausea... (Heavily Contaminated)");
        return;
    }

    if (rand < CONFIG.POISON_CHANCE) {
        player.addEffect("hunger", 600, { amplifier: 1 }); 
        player.sendMessage("§cStomach feels weird... (Contaminated)");
    }
}

function getThirst(player) {
    const val = player.getDynamicProperty("hydration:thirst");
    if (typeof val === "number") {
        return val;
    }
    return CONFIG.MAX_THIRST;
}

function setThirst(player, value) {
    const clamped = Math.max(0, Math.min(value, CONFIG.MAX_THIRST));
    player.setDynamicProperty("hydration:thirst", clamped);
}

function addThirst(player, amount) {
    const current = getThirst(player);
    setThirst(player, current + amount);
}