"""Is a settler's 4 movement points a per-turn budget, or a per-action one?

Part 1 §4.2 of `docs/WORLD-SPEC.md`: "A citizen's avatar (`settler` sheet) has
mode `ground`, `speed 4`, no fuel: 4 movement points per turn, refilled at
freeze." Reading the code, nothing accumulates movement across a turn —
`Move.validate` checks one path against `speed` and the movement phase calls
`walkable_prefix(..., speed, ...)` once per row — so two `move` rows in one
batch should walk twice the allowance for 2 AP.

This checks it on the world rather than on the reading: one citizen, two `move`
rows of four plain tiles each, one turn, and where they end up.

    python research/hesper/phase-rounds/movement_pool_check.py

It runs against the scratch world at ~/data/hesper-bench (see RESULTS.md), never
the live one.
"""

import json
import sqlite3
import sys
import time
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[3]))

from hesper import db, turn as turn_mod                 # noqa: E402
from hesper.core import loader                          # noqa: E402

DB = Path.home() / "data" / "hesper-bench" / "h.db"
WALKABLE = ("plain", "forest", "hill", "grass", "meadow", "steppe")


def main():
    conn = db.connect(str(DB))
    db.apply_migrations(conn)
    conn.row_factory = sqlite3.Row
    turn = int(db.meta_get(conn, "current_turn", "0")) + 1
    load_result = loader.load(laws_dir=None, law_version=1, turn=turn, conn=conn)
    db.apply_module_migrations(conn, load_result)

    # A citizen with eight walkable tiles due east of them.
    chosen = None
    for row in conn.execute(
            "SELECT p.player_id, t.thing_id, t.x, t.y FROM players p "
            "JOIN things t ON t.thing_id = p.avatar_thing_id ORDER BY p.player_id"):
        line = [(row["x"] + i, row["y"]) for i in range(1, 9)]
        kinds = [conn.execute("SELECT terrain, improvement FROM tiles WHERE x = ? AND y = ?",
                              (x, y)).fetchone() for x, y in line]
        if all(k is not None and k["terrain"] in WALKABLE for k in kinds):
            chosen = (row["player_id"], row["thing_id"], row["x"], row["y"], line)
            break
    if chosen is None:
        raise SystemExit("no citizen with eight walkable tiles east of them")
    player_id, avatar, x, y, line = chosen

    rid = "rmp%09x" % int(time.time() % 1e9)
    conn.execute(
        "INSERT INTO requests (request_id, target_turn, at_ms, route, player_id, "
        "client_action_id, body_sha256, body_json, queued) "
        "VALUES (?, ?, ?, 'POST /api/actions', ?, ?, '0', '{}', 1)",
        (rid, turn, int(time.time() * 1000), player_id, "mp-" + rid))
    for idx, steps in enumerate((line[:4], line[4:])):
        conn.execute(
            "INSERT INTO actions (action_id, request_id, idx, type, payload_json, "
            "ap_cost, target_turn, status) VALUES (?, ?, ?, 'move', ?, 1, ?, 'queued')",
            (rid + str(idx), rid, idx,
             json.dumps({"path": [[a, b] for a, b in steps]}), turn))
    conn.commit()

    print(f"citizen  {player_id} at ({x}, {y}), speed 4, two move rows of 4 tiles, 2 AP")
    turn_mod.resolve(conn, None, load_result,
                     sealer=lambda *a, **k: {"ok": False, "reason": "bench", "note": None},
                     git_sealer=lambda *a, **k: {"ok": False, "reason": "bench", "note": None})
    end = conn.execute("SELECT x, y FROM things WHERE thing_id = ?", (avatar,)).fetchone()
    walked = int(end["x"]) - x
    print(f"ended    ({end['x']}, {end['y']}) — walked {walked} tiles in one turn")
    for row in conn.execute(
            "SELECT idx, status, result_json FROM actions WHERE request_id = ? ORDER BY idx",
            (rid,)):
        record = json.loads(row["result_json"] or "{}")
        print(f"  row {row['idx']}  {row['status']:<9} {record.get('outcome')} "
              f"cost {record.get('cost')} to {record.get('to')}")
    print()
    print("4 movement points a turn" if walked <= 4 else
          "8 tiles on a budget of 4: movement points are per action, not per turn")
    conn.close()


if __name__ == "__main__":
    main()
