const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");

canvas.width = 1280;
canvas.height = 720;

const loginBox = document.getElementById("loginBox");
const registerBox = document.getElementById("registerBox");

const loginUser = document.getElementById("loginUser");
const loginPass = document.getElementById("loginPass");
const loginBtn = document.getElementById("loginBtn");

const regUser = document.getElementById("regUser");
const regPass = document.getElementById("regPass");
const regBtn = document.getElementById("regBtn");

const switchToRegister = document.getElementById("switchToRegister");
const switchToLogin = document.getElementById("switchToLogin");

const shopWindow = document.getElementById("shopWindow");
const shopList = document.getElementById("shopList");

let ws = null;
let maps = {};
let tileConfig = {};
let lastServerUpdate = 0;

let player = {
    id: null,
    x: 100,
    y: 100,
    world: "stadt"
};
player.health = 100;
player.hunger = 100;
player.thirst = 100;

player.inventory = [];
player.money = 1000;





let loggedIn = false;
let otherPlayers = [];
let keys = {};
let shops = [];
let atms = [];

let cars = [];
let drivingCarId = null;



let objectConfig = {};

fetch("/objectConfig.json")
    .then(res => res.json())
    .then(data => objectConfig = data);


// -------------------------------------------------------------
// Tiles laden
// -------------------------------------------------------------
fetch("/tiles.json")
    .then(res => res.json())
    .then(data => {
        tileConfig = data;
        console.log("TileConfig geladen:", tileConfig);
    });

// -------------------------------------------------------------
// REGISTER
// -------------------------------------------------------------
    regBtn.onclick = async () => {
        const username = regUser.value;
        const password = regPass.value;

        const res = await fetch("/api/register", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ username, password })
        });

        const data = await res.json();

        if (!data.ok) {
            alert(data.error);
            return;
        }

        alert("Registrierung erfolgreich!");
        registerBox.style.display = "none";
        loginBox.style.display = "block";
    };

    // -------------------------------------------------------------
    // LOGIN
    // -------------------------------------------------------------
    loginBtn.onclick = async () => {
        const username = loginUser.value;
        const password = loginPass.value;

        const res = await fetch("/api/login", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ username, password })
        });

        const data = await res.json();

        if (!data.ok) {
            alert(data.error);
            return;
        }

        loginBox.style.display = "none";
        canvas.style.display = "block";

        startMultiplayer(data.token);
    };




// Hilfsfunktion: Spieler holen
function getPlayer(playerId) {
    return playersOnline.get(playerId);
}

// BANK: PIN prüfen
async function handleBankPinCheck(playerId, data, ws) {
    const p = getPlayer(playerId);
    if (!p) return;

    const pin = Number(data.pin) || 0;

    const [rows] = await db.query("SELECT pin FROM players WHERE id=?", [playerId]);
    if (!rows.length) return;

    if (rows[0].pin === pin) {
        ws.send(JSON.stringify({ type: "bank_pin_ok" }));
    } else {
        ws.send(JSON.stringify({ type: "bank_pin_fail" }));
    }
}

// BANK: Fenster öffnen (Kontostand + Bargeld)
async function handleBankOpen(playerId, ws) {
    const p = getPlayer(playerId);
    if (!p) return;

    ws.send(JSON.stringify({
        type: "bank_open",
        money: p.state.money,
        bank: p.state.bank
    }));
}

// BANK: Einzahlen
async function handleBankDeposit(playerId, data, ws) {
    const p = getPlayer(playerId);
    if (!p) return;

    const amount = Number(data.amount) || 0;
    if (amount <= 0) return;
    if (p.state.money < amount) return;

    p.state.money -= amount;
    p.state.bank += amount;

    await db.query(
        "UPDATE players SET money=?, bank=? WHERE id=?",
        [p.state.money, p.state.bank, playerId]
    );

    ws.send(JSON.stringify({
        type: "bank_update",
        money: p.state.money,
        bank: p.state.bank
    }));
}

// BANK: Auszahlen
async function handleBankWithdraw(playerId, data, ws) {
    const p = getPlayer(playerId);
    if (!p) return;

    const amount = Number(data.amount) || 0;
    if (amount <= 0) return;
    if (p.state.bank < amount) return;

    p.state.bank -= amount;
    p.state.money += amount;

    await db.query(
        "UPDATE players SET money=?, bank=? WHERE id=?",
        [p.state.money, p.state.bank, playerId]
    );

    ws.send(JSON.stringify({
        type: "bank_update",
        money: p.state.money,
        bank: p.state.bank
    }));
}

// BANK: Geld an anderen Spieler senden (Bank → Bank)
async function handleBankTransfer(playerId, data, ws) {
    const p = getPlayer(playerId);
    if (!p) return;

    const targetId = Number(data.targetId);
    const amount = Number(data.amount) || 0;
    if (amount <= 0) return;

    const t = getPlayer(targetId);
    if (!t) return;
    if (p.state.bank < amount) return;

    p.state.bank -= amount;
    t.state.bank += amount;

    await db.query("UPDATE players SET bank=? WHERE id=?", [p.state.bank, playerId]);
    await db.query("UPDATE players SET bank=? WHERE id=?", [t.state.bank, targetId]);

    ws.send(JSON.stringify({
        type: "bank_update",
        money: p.state.money,
        bank: p.state.bank
    }));

    t.ws.send(JSON.stringify({
        type: "bank_update",
        money: t.state.money,
        bank: t.state.bank
    }));
}




// -------------------------------------------------------------
// UI SWITCH
// -------------------------------------------------------------
switchToRegister.onclick = () => {
    loginBox.style.display = "none";
    registerBox.style.display = "block";
    canvas.style.display = "none";
};

switchToLogin.onclick = () => {
    registerBox.style.display = "none";
    loginBox.style.display = "block";
    canvas.style.display = "none";
};

// -------------------------------------------------------------
// MULTIPLAYER STARTEN
// -------------------------------------------------------------
function startMultiplayer(token) {
    ws = new WebSocket("ws://45.81.233.187:5555");

    ws.onopen = () => {
        ws.send(JSON.stringify({ type: "auth", token }));
    };

    ws.onmessage = ev => {
        const msg = JSON.parse(ev.data);

        if (msg.type === "auth_ok") {
            player.id = msg.id;
            maps = msg.maps;
            document.getElementById("topMenu").style.display = "flex";
            document.getElementById("statusWindow").style.display = "block";
            document.getElementById("inventoryWindow").style.display = "block";
            
            player.inventory = msg.inventory || [];
            document.getElementById("inventoryWindow").style.display = "block";
            renderInventoryWindow();
            canvas.style.display = "block";

            console.log("MAPS GELADEN:", maps);
           
            const map = maps[player.world];
            if (map && map.spawn) {
                player.x = map.spawn.x;
                player.y = map.spawn.y;
            }
            //shops=map.shops;
            loggedIn = true;

            return;
        }
        if (msg.type === "state") {
            lastServerUpdate = Date.now();

            const me = msg.players.find(p => p.id === player.id);
            if (me) {
                // nur setzen, wenn wir NICHT gerade bewegen
                if (!keys["w"] && !keys["a"] && !keys["s"] && !keys["d"]) {
                    player.x = me.x;
                    player.y = me.y;
                }
                player.world = me.world;
                player.money = me.money;
                player.bank = me.bank;
                player.health = me.health;
                player.hunger = me.hunger;
                player.thirst = me.thirst;
                player.inventory = me.inventory;
                //console.log("geld:", player.money);
            }

            otherPlayers = msg.players.filter(p => p.id !== player.id);
            renderInventoryWindow();
            updateStatusUI();
        }

        if (msg.type === "npc_dialog") {
            alert("NPC sagt: " + msg.text);
        }
        if (msg.type === "shop_open") {
            const shopWindow = document.getElementById("shopWindow");
            const shopList = document.getElementById("shopList");

            shopWindow.style.display = "block";
            shopList.innerHTML = "";

            msg.items.forEach(item => {
                const div = document.createElement("div");
                div.style.padding = "5px";
                div.style.borderBottom = "1px solid #333";
                div.innerHTML = `
                    ${item.name} - ${item.price}$
                    <button onclick="buyItem('${item.id}')">Kaufen</button>
                `;
                shopList.appendChild(div);
            });
        }

        if (msg.type === "shop_error") {
            alert(msg.msg);
        }
        if (msg.type === "item_used") {
            console.log(msg.hunger)
            console.log(msg.thirst)
            player.hunger = msg.hunger;
            player.thirst = msg.thirst;
            player.health = msg.health;
            player.inventory = msg.inventory;

            updateStatusWindow();
            renderInventoryWindow();
        }
        if (msg.type === "atm_open") {
            const pin = prompt("PIN eingeben");
            ws.send(JSON.stringify({ type: "bank_pin_check", pin }));
        }
        if (msg.type === "bank_pin_ok") {
             console.log("bank_pin_ok KOMMT AN");
            ws.send(JSON.stringify({ type: "bank_open" }));
        }
        if (msg.type === "bank_pin_fail") {
            alert("Falsche PIN!");
        }
        if (msg.type === "bank_open") {
            console.log("BANK_OPEN KOMMT AN");
            openATMWindow(msg.money, msg.bank);
        }
        if (msg.type === "bank_update") {
            document.getElementById("atmMoney").innerText = msg.money;
            document.getElementById("atmBank").innerText = msg.bank;
        }
        // im ws.onmessage ergänzen:
        if (msg.type === "cars") {
            cars = msg.cars;
            const mine = cars.find(c => c.driverId === player.id);
            drivingCarId = mine ? mine.id : null;
        }



        if (msg.type === "object_interact") {
            if (msg.action === "loot") {
                alert("Du hast die Kiste geöffnet!");
            }
        }

            // Map-Daten
        if (msg.type === "map_data") {
            tiles = msg.tiles;
            doors = msg.doors || [];
            objects = msg.objects || [];
            shops = msg.shops || [];   // <-- WICHTIG
            atms = msg.atms || [];
            spawn = msg.spawn;

             console.log("shops:", shops);
             console.log("atms:", atms);
            return;
        }

    };
}

function openATMWindow(money, bank) {
    document.getElementById("atmMoney").innerText = money;
    document.getElementById("atmBank").innerText = bank;
    document.getElementById("atmBox").style.display = "block";
}

function closeATM() {
    document.getElementById("atmBox").style.display = "none";
}

function atmDeposit() {
    const amount = Number(document.getElementById("atmAmount").value);
    ws.send(JSON.stringify({ type: "bank_deposit", amount }));
}

function atmWithdraw() {
    const amount = Number(document.getElementById("atmAmount").value);
    ws.send(JSON.stringify({ type: "bank_withdraw", amount }));
}

function atmTransfer() {
    const amount = Number(document.getElementById("atmAmount").value);
    const targetId = Number(document.getElementById("atmTarget").value);
    ws.send(JSON.stringify({ type: "bank_transfer", amount, targetId }));
}








function updateStatusUI() {
    const hungerBar = document.getElementById("hungerValue");
    const thirstBar = document.getElementById("thirstValue");
    const moneyLabel = document.getElementById("moneyValue");

    if (hungerBar) hungerBar.textContent = player.hunger;
    if (thirstBar) thirstBar.textContent = player.thirst;
    if (moneyLabel) moneyLabel.textContent = player.money;
}

function openATM(atm) {
    ws.send(JSON.stringify({
        type: "bank_pin_check",
        pin: prompt("PIN eingeben")
    }));
}


function useItem(itemId) {
    console.log("useItem wurde ausgeführt mit:", itemId);
    ws.send(JSON.stringify({
        type: "use_item",
        itemId
    }));
}


function buyItem(itemId) {
    ws.send(JSON.stringify({
        type: "shop_buy",
        itemId
    }));
}



// -------------------------------------------------------------
// CAMERA (mit Zentrierung bei kleinen Maps)
// -------------------------------------------------------------
function getCamera() {
    const map = maps[player.world];
    if (!map || !map.tiles || map.tiles.length === 0) {
        return { x: 0, y: 0 };
    }

    const mapWidth = map.tiles[0].length * 32;
    const mapHeight = map.tiles.length * 32;

    let camX = player.x - canvas.width / 2;
    let camY = player.y - canvas.height / 2;

    if (mapWidth < canvas.width) {
        camX = -(canvas.width / 2 - mapWidth / 2);
    } else {
        if (camX < 0) camX = 0;
        if (camX > mapWidth - canvas.width)
            camX = mapWidth - canvas.width;
    }

    if (mapHeight < canvas.height) {
        camY = -(canvas.height / 2 - mapHeight / 2);
    } else {
        if (camY < 0) camY = 0;
        if (camY > mapHeight - canvas.height)
            camY = mapHeight - canvas.height;
    }

    return { x: camX, y: camY };
}

// -------------------------------------------------------------
// MOVEMENT + Collision
// -------------------------------------------------------------
document.addEventListener("keydown", e => {
    keys[e.key] = true;

    if (!ws) return;

    if (e.key.toLowerCase() === "e") {
        ws.send(JSON.stringify({
            type: "interact",
            x: player.x,
            y: player.y,
            world: player.world
        }));
    }
});
// Shop schließen (ESC)
document.addEventListener("keydown", e => {
    if (e.key === "Escape") {
        shopWindow.style.display = "none";
    }
});

document.addEventListener("keyup", e => {
    keys[e.key] = false;
});

function canMoveTo(nx, ny) {
    const map = maps[player.world];
    if (!map || !map.tiles) return true;

    const tileX = Math.floor(nx / 32);
    const tileY = Math.floor(ny / 32);

    // TILE COLLISION
    const tileId = map.tiles[tileY]?.[tileX];
    const tile = tileConfig[tileId];
    if (tile && tile.collision) return false;

    // OBJECT COLLISION
    if (map.objects) {
        for (const obj of map.objects) {
            const cfg = objectConfig[obj.type];
            if (!cfg || !cfg.collision) continue;

            const ox = obj.x;
            const oy = obj.y - (cfg.height - 32); // Objekt höher als Tile
            const ow = cfg.width;
            const oh = cfg.height;

            // Spieler-Hitbox (30x30)
            const px = nx;
            const py = ny;
            const pw = 30;
            const ph = 30;

            const hit =
                px < ox + ow &&
                px + pw > ox &&
                py < oy + oh &&
                py + ph > oy;

            if (hit) return false;
        }
    }

    return true;
}
function updateNeeds() {
    player.hunger -= 0.002;
    player.thirst -= 0.004;

    if (player.hunger < 0) player.hunger = 0;
    if (player.thirst < 0) player.thirst = 0;

    if (player.hunger === 0 || player.thirst === 0) {
        player.health -= 0.01;
        if (player.health < 0) player.health = 0;
    }
}

function updateStatusWindow() {
    const status = document.getElementById("statusWindow");

    status.innerHTML = `
        Leben: ${Math.round(player.health)}<br>
        Hunger: ${Math.round(player.hunger)}<br>
        Durst: ${Math.round(player.thirst)}<br>
        Geld: ${player.money}$
    `;
}

function updateMovement() {
    let moved = false;

    let nx = player.x;
    let ny = player.y;

    /*if (keys["w"]) ny -= 5;
    if (keys["s"]) ny += 5;
    if (keys["a"]) nx -= 5;
    if (keys["d"]) nx += 5;*/

    if (keys["w"]) { ny -= 5; moved = true; }
    if (keys["s"]) { ny += 5; moved = true; }
    if (keys["a"]) { nx -= 5; moved = true; }
    if (keys["d"]) { nx += 5; moved = true; }

    if (canMoveTo(nx, ny)) {
        player.x = nx;
        player.y = ny;

        // FIX: nur senden, wenn WS existiert und verbunden ist
    if (ws && moved && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({
                type: "move",
                x: nx,
                y: ny,
                //health: player.health,
                //hunger: player.hunger,
                //thirst: player.thirst
            }));
        }
    }


    if (ws && player.id && moved) {
        ws.send(JSON.stringify({
            type: "move",
            x: player.x,
            y: player.y
        }));
    }
    

}

function renderInventoryWindow() {
   // console.log("renderInventoryWindow wurde ausgeführt");
    const list = document.getElementById("inventoryList");
    if (!list) return;

    list.innerHTML = "";

    (player.inventory || []).forEach(item => {
        const div = document.createElement("div");
        div.style.display = "flex";
        div.style.justifyContent = "space-between";
        div.style.padding = "5px";
        div.style.borderBottom = "1px solid #333";

        div.innerHTML = `
            <span>${item.name || item.id} x${item.amount}</span>
            <button class="useItemBtn" data-id="${item.id}">Benutzen</button>
        `;

        list.appendChild(div);
    });

    const buttons = document.querySelectorAll(".useItemBtn");
    //console.log("Buttons gefunden:", buttons.length);
    //console.log("Buttons gefunden:", document.querySelectorAll(".useItemBtn").length);

    document.querySelectorAll(".useItemBtn").forEach(btn => {
        btn.onclick = () => {
            //console.log("Button wurde geklickt:", btn.dataset.id);
            //console.log("Buttons gefunden:", document.querySelectorAll(".useItemBtn").length);

            useItem(btn.dataset.id);
        };
    });
}
// -------------------------------------------------------------
// RENDERING
// -------------------------------------------------------------
function renderMap() {
    const map = maps[player.world];
    if (!map || !map.tiles) return;

    const cam = getCamera();

    for (let y = 0; y < map.tiles.length; y++) {
        for (let x = 0; x < map.tiles[y].length; x++) {
            const tileId = map.tiles[y][x];
            const tile = tileConfig[tileId];

            if (!tile) continue;

            ctx.fillStyle = tile.color;

            ctx.fillRect(
                x * 32 - cam.x,
                y * 32 - cam.y,
                32,
                32
            );
        }
    }
}

function renderDoors() {
    const map = maps[player.world];
    if (!map || !map.doors) return;

    const cam = getCamera();

    map.doors.forEach(d => {
        ctx.fillStyle = "orange";
        ctx.fillRect(
            d.x - cam.x,
            d.y - cam.y,
            30,
            30
        );
    });
}

function renderPlayers() {
    const cam = getCamera();

    ctx.fillStyle = "yellow";
    ctx.fillRect(
        player.x - cam.x,
        player.y - cam.y,
        20,
        20
    );

    otherPlayers.forEach(p => {
        if (p.world === player.world) {
            ctx.fillStyle = "cyan";
            ctx.fillRect(
                p.x - cam.x,
                p.y - cam.y,
                20,
                20
            );
        }
    });
}

function renderObjects() {
    const map = maps[player.world];
    if (!map || !map.objects) return;

    const cam = getCamera();

    map.objects.forEach(o => {
        const cfg = objectConfig[o.type];
        if (!cfg) return;

        ctx.fillStyle = cfg.color;
        ctx.fillRect(
            o.x - cam.x,
            o.y - (cfg.height - 32) - cam.y,
            cfg.width,
            cfg.height
        );
    });
}
function renderShops() {
    const cam = getCamera();

    shops.forEach(s => {
        const px = s.x * 32 - cam.x;
        const py = s.y * 32 - cam.y;

        ctx.fillStyle = "yellow";
        ctx.fillRect(px, py, 32, 32);

        ctx.strokeStyle = "black";
        ctx.strokeRect(px, py, 32, 32);
    });
}
function renderATMs() {
    const cam = getCamera();
    atms.forEach(a => {
        const px = a.x * 32 - cam.x;   // klein!
        const py = a.y * 32 - cam.y;   // klein!

        ctx.fillStyle = "blue";
        ctx.fillRect(px, py, 32, 32);
        ctx.strokeStyle = "black";     // optional, wie bei Shops
        ctx.strokeRect(px, py, 32, 32);
    });
}


function render() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    renderMap();
    renderObjects();
    renderShops();
    renderATMs();
    renderDoors();
    renderPlayers();

    requestAnimationFrame(render);
}

// -------------------------------------------------------------
// GAME LOOP
// -------------------------------------------------------------
function gameLoop() {
    updateMovement();
    setTimeout(gameLoop, 16);
    updateStatusWindow();
    //updateNeeds();
}


render();
gameLoop();
