(function () {
    // poker_sit.js — Poker Seat Entity Script
    //
    // Attach to each seat pad entity. userData must contain:
    //   { "tableID": "{uuid-of-table-mesh-entity}", "pokerID": "main", "seatIndex": 3 }
    //
    // tableID  — Overte entity UUID of the table mesh, used for position calculations
    // pokerID  — poker table slug used for API calls (matches table config id)

    var constants   = Script.require(Script.resolvePath("poker_constants.js"));
    var POKER_SEATS = constants.POKER_SEATS;
    var API_BASE    = constants.API_BASE;
    var POKER_BASE  = constants.POKER_BASE;
    var JUMP_ACTION = 50;

    var _entityID  = null;
    var _tableID   = null;
    var _pokerID   = null;
    var _seatIndex = null;
    var _seatData  = null;
    var _token     = null;
    var _username  = null;
    var _busy      = false;
    var isSeated   = false;

    // ── helpers ──────────────────────────────────────────────────

    function getUserData(entityID) {
        try {
            var props = Entities.getEntityProperties(entityID, ["userData"]);
            return JSON.parse(props.userData || "{}");
        } catch (e) {
            print("[pokerSeat] userData parse error: " + e);
            return {};
        }
    }

    function getTableSeatCount() {
        var ud = getUserData(_tableID);
        return ud.seatCount || 7;
    }

    function getSeatPosition() {
        var tableProps = Entities.getEntityProperties(_tableID, ["position", "rotation"]);
        var worldOffset = Vec3.multiplyQbyV(tableProps.rotation, _seatData.offset);
        return Vec3.sum(tableProps.position, worldOffset);
    }

    function getSeatRotation() {
        var tableProps = Entities.getEntityProperties(_tableID, ["rotation"]);
        var tableYaw = Quat.safeEulerAngles(tableProps.rotation).y;
        return Quat.fromPitchYawRollDegrees(0, tableYaw + _seatData.yaw, 0);
    }

    function notify(msg) {
        Window.displayAnnouncement(msg);
    }

    // ── session ──────────────────────────────────────────────────

    function ensureSession(cb) {
        if (_token) { cb(null, _token); return; }

        _username = MyAvatar.displayName;
        if (!_username) { cb("Not logged in to Overte"); return; }

        print("[pokerSeat] requesting session from: " + API_BASE + "/session for " + _username);
        var xhr = new XMLHttpRequest();
        xhr.open("POST", API_BASE + "/session", true);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200) {
                try {
                    _token = JSON.parse(xhr.responseText).token;
                    Script.setTimeout(function () { _token = null; }, 5 * 60 * 1000);
                    cb(null, _token);
                } catch (e) { cb("Session parse error"); }
            } else if (xhr.status === 403) {
                cb("Must be in-world to sit down");
            } else {
                cb("Session error (" + xhr.status + ")");
            }
        };
        xhr.send(JSON.stringify({ username: _username }));
    }

    // ── sit / stand ──────────────────────────────────────────────

    function doStand(cb) {
        var tok = _token;
        var xhr = new XMLHttpRequest();
        xhr.open("POST", POKER_BASE + "/tables/" + _pokerID + "/stand", true);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.setRequestHeader("Authorization", "Bearer " + tok);
        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            _token = null;
            if (isSeated) {
                MyAvatar.endSit(getSeatPosition(), getSeatRotation());
                isSeated = false;
                Entities.editEntity(_entityID, { locked: false });
                Entities.editEntity(_entityID, { visible: true });
                Entities.editEntity(_entityID, { locked: true });
                Controller.actionEvent.disconnect(onActionEvent);
                Messages.sendMessage("poker:seat", JSON.stringify({
                    event:     "stand",
                    tableID:   _tableID,
                    seatIndex: _seatIndex,
                    username:  _username,
                }));
            }
            if (cb) cb();
        };
        xhr.send(JSON.stringify({ seatIndex: parseInt(_seatIndex) }));
    }

    function onSit() {
        print("[pokerSeat] onSit called, seat=" + _seatIndex + " isSeated=" + isSeated + " _busy=" + _busy + " _seatData=" + (_seatData ? "ok" : "null"));
        if (isSeated || _busy) return;
        _busy = true;
        Script.setTimeout(function () { _busy = false; }, 3000);

        if (!_seatData) {
            notify("Seat not configured (index " + _seatIndex + ")");
            _busy = false;
            return;
        }

        ensureSession(function (err) {
            if (err) { notify(err); _busy = false; return; }

            var xhr = new XMLHttpRequest();
            xhr.open("POST", POKER_BASE + "/tables/" + _pokerID + "/sit", true);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader("Authorization", "Bearer " + _token);
            xhr.onreadystatechange = function () {
                if (xhr.readyState !== 4) return;
                print("[pokerSeat] sit response: " + xhr.status + " " + xhr.responseText);
                if (xhr.status === 200) {
                    MyAvatar.beginSit(getSeatPosition(), getSeatRotation());
                    isSeated = true;
                    Entities.editEntity(_entityID, { locked: false });
                    Entities.editEntity(_entityID, { visible: false });
                    Entities.editEntity(_entityID, { locked: true });
                    Controller.actionEvent.connect(onActionEvent);
                    Messages.sendMessage("poker:seat", JSON.stringify({
                        event:     "sit",
                        tableID:   _tableID,
                        pokerID:   _pokerID,
                        seatIndex: _seatIndex,
                        username:  _username,
                    }));
                    _busy = false;
                } else {
                    try {
                        var resp = JSON.parse(xhr.responseText);
                        if (resp.error === "already seated") {
                            print("[pokerSeat] recovering stale seat, standing first");
                            doStand(function () { onSit(); });
                            return;
                        }
                        notify(resp.error || "Could not sit down");
                    } catch (e) {
                        notify("Could not sit down (" + xhr.status + ")");
                    }
                    _busy = false;
                }
            };
            xhr.send(JSON.stringify({ seatIndex: parseInt(_seatIndex) }));
        });
    }

    function onStand() {
        if (!isSeated) return;
        doStand(null);
    }

    function onActionEvent(action, value) {
        if (action === JUMP_ACTION && value > 0) {
            onStand();
        }
    }

    // ── lifecycle ────────────────────────────────────────────────

    this.preload = function (entityID) {
        _entityID = entityID;

        var ud = getUserData(entityID);
        _tableID   = ud.tableID   || null;
        _pokerID   = ud.pokerID   || null;
        _seatIndex = ud.seatIndex !== undefined ? String(ud.seatIndex) : null;

        if (!_tableID || !_pokerID || _seatIndex === null) {
            print("[pokerSeat] missing tableID, pokerID, or seatIndex in userData on " + entityID);
            return;
        }

        var seatCount = getTableSeatCount();
        var layout    = POKER_SEATS[seatCount];
        if (!layout || layout[parseInt(_seatIndex)] === undefined) {
            print("[pokerSeat] no layout for seatCount=" + seatCount + " index=" + _seatIndex);
            return;
        }

        _seatData = layout[parseInt(_seatIndex)];
        print("[pokerSeat] loaded seat " + _seatIndex + " at table " + _tableID);
    };

    this.startNearTrigger  = function () { onSit(); };
    this.stopNearTrigger   = function () {};
    this.startFarTrigger   = function () { onSit(); };
    this.stopFarTrigger    = function () {};
    this.clickDownOnEntity = function () { onSit(); };
    this.clickUpOnEntity   = function () {};

    this.unload = function () {
        if (isSeated) {
            Controller.actionEvent.disconnect(onActionEvent);
            isSeated = false;
        }
        _token = null;
    };
});
