#!/usr/bin/env bash
set -Eeuo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
migration="$repo_root/deploy/migrations/20260913_bee_transaction_durability.sql"
work_dir="$(mktemp -d)"
socket="$work_dir/mariadb.sock"
pid_file="$work_dir/mariadb.pid"

cleanup() {
  if [[ -f "$pid_file" ]]; then
    kill "$(cat "$pid_file")" 2>/dev/null || true
    wait "$(cat "$pid_file")" 2>/dev/null || true
  fi
  rm -rf -- "$work_dir"
}
trap cleanup EXIT

mariadb-install-db --no-defaults --datadir="$work_dir/data" >/dev/null
mariadbd --no-defaults --datadir="$work_dir/data" --socket="$socket" \
  --pid-file="$pid_file" --skip-networking --log-error="$work_dir/mariadb.log" &
for _ in {1..100}; do
  [[ -S "$socket" ]] && break
  sleep 0.1
done
[[ -S "$socket" ]]

sql() { mariadb --no-defaults --socket="$socket" "$@"; }
create_table() {
  local database="$1"
  sql -e "CREATE DATABASE \`$database\`; CREATE TABLE \`$database\`.bee_transaction_log (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    transaction_id VARCHAR(191) NULL,
    test_id BIGINT NULL,
    timestamp BIGINT NOT NULL DEFAULT 0,
    instrument_id BIGINT NOT NULL DEFAULT 0,
    order_name VARCHAR(191) NOT NULL DEFAULT '',
    side INT NOT NULL DEFAULT 0,
    amount DOUBLE NOT NULL DEFAULT 0,
    position DOUBLE NOT NULL DEFAULT 0,
    price DOUBLE NOT NULL DEFAULT 0,
    pnl DOUBLE NOT NULL DEFAULT 0,
    equity DOUBLE NOT NULL DEFAULT 0,
    average_price DOUBLE NOT NULL DEFAULT 0,
    type INT NOT NULL DEFAULT 0,
    fee DOUBLE NOT NULL DEFAULT 0
  );"
}
apply_migration() { sql "$1" < "$migration"; }
index_shape() {
  sql --batch --skip-column-names "$1" -e "SELECT CONCAT(NON_UNIQUE, ':', GROUP_CONCAT(CONCAT(COLUMN_NAME, ':', IFNULL(SUB_PART, 'FULL')) ORDER BY SEQ_IN_INDEX))
    FROM INFORMATION_SCHEMA.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bee_transaction_log'
      AND INDEX_NAME = 'uq_bee_transaction_identity'
    GROUP BY NON_UNIQUE;"
}

run_python_writer() {
  local database="$1" transaction_id="$2" price="$3"
  python3 - "$repo_root" "$socket" "$database" "$transaction_id" "$price" <<'PY'
import importlib.util
import logging
import pathlib
import subprocess
import sys
import types

repo, socket, database, transaction_id, price = sys.argv[1:]
sys.modules["redis"] = types.SimpleNamespace()
sys.modules["ConnectionPool"] = types.SimpleNamespace(ConnectionPool=object)
sys.modules["dotenv"] = types.SimpleNamespace(load_dotenv=lambda *_: None)
mysql = types.ModuleType("mysql")
connector = types.ModuleType("mysql.connector")
connector.Error = Exception
mysql.connector = connector
sys.modules["mysql"] = mysql
sys.modules["mysql.connector"] = connector

spec = importlib.util.spec_from_file_location(
    "bee_transaction_handler", pathlib.Path(repo) / "beeDataHandler/beeDataHandler.py"
)
handler = importlib.util.module_from_spec(spec)
basic_config = logging.basicConfig
logging.basicConfig = lambda **_kwargs: None
try:
    spec.loader.exec_module(handler)
finally:
    logging.basicConfig = basic_config

class Cursor:
    def execute(self, query, params):
        for value in params:
            literal = "'" + value.replace("'", "''") + "'" if isinstance(value, str) else str(value)
            query = query.replace("%s", literal, 1)
        subprocess.run(
            ["mariadb", "--no-defaults", f"--socket={socket}", database, "-e", query],
            check=True,
        )

class Connection:
    def cursor(self): return Cursor()
    def commit(self): return None

class Pool:
    def get_connection(self): return Connection()
    def release_connection(self, _connection): return None

transaction = {
    "id": transaction_id, "test_id": 42, "timestamp": 10, "instrument_id": 7,
    "order_name": "synthetic-python", "side": 1, "amount": 1, "position": 1,
    "price": float(price), "pnl": 0, "equity": float(price), "average_price": 0,
    "type": 2, "fee": 0,
}
assert handler.add_transaction_to_db(Pool(), transaction)
PY
}

run_php_writer() {
  local database="$1" transaction_id="$2" price="$3"
  php -r '
    require $argv[1] . "/classes/MysqliHelper.php";
    require $argv[1] . "/classes/ResultsV2Store.php";
    $db = mysqli_init();
    $db->real_connect("localhost", "fixture", "", $argv[3], 0, $argv[2]);
    $store = new ResultsV2Store($db);
    $first = [
      "id" => "42-1000-1", "test_id" => 42, "timestamp" => 10, "instrument_id" => 7,
      "order_name" => "synthetic-python", "side" => 1, "amount" => 1, "position" => 1,
      "price" => 100, "pnl" => 0, "equity" => 100, "average_price" => 0,
      "type" => 2, "fee" => 0,
    ];
    $transaction = [
      "id" => $argv[4], "test_id" => 42, "timestamp" => 11, "instrument_id" => 7,
      "order_name" => "synthetic-php", "side" => 2, "amount" => 1, "position" => 0,
      "price" => (float)$argv[5], "pnl" => 0, "equity" => (float)$argv[5],
      "average_price" => 0, "type" => 2, "fee" => 0,
    ];
    if (!$store->reconcileTransactions(42, [$first, $transaction])) exit(1);
  ' "$repo_root" "$socket" "$database" "$transaction_id" "$price"
}

create_table valid_case
sql valid_case -e "INSERT INTO bee_transaction_log (test_id, transaction_id) VALUES (1, 'same'), (2, 'same');"
apply_migration valid_case
[[ "$(index_shape valid_case)" == "0:test_id:FULL,transaction_id:FULL" ]]
sql valid_case -e "INSERT INTO bee_transaction_log (test_id, transaction_id, timestamp) VALUES (1, 'same', 10)
  ON DUPLICATE KEY UPDATE timestamp = VALUES(timestamp);"
[[ "$(sql --batch --skip-column-names valid_case -e "SELECT CONCAT(COUNT(*), ':', SUM(test_id=1), ':', SUM(test_id=2), ':', SUM(timestamp=10)) FROM bee_transaction_log;")" == "2:1:1:1" ]]
apply_migration valid_case
[[ "$(index_shape valid_case)" == "0:test_id:FULL,transaction_id:FULL" ]]

create_table retry_case
sql retry_case -e "INSERT INTO bee_transaction_log (test_id, transaction_id) VALUES (1, 'dup'), (1, 'dup');"
if apply_migration retry_case >/dev/null 2>&1; then
  echo "duplicate preflight unexpectedly succeeded" >&2
  exit 1
fi
[[ -z "$(index_shape retry_case)" ]]
sql retry_case -e "DELETE FROM bee_transaction_log WHERE id = 2;"
apply_migration retry_case
[[ "$(index_shape retry_case)" == "0:test_id:FULL,transaction_id:FULL" ]]

create_table invalid_case
sql invalid_case -e "INSERT INTO bee_transaction_log (test_id, transaction_id) VALUES (NULL, 'x'), (2, '');"
if apply_migration invalid_case >/dev/null 2>&1; then
  echo "invalid identity preflight unexpectedly succeeded" >&2
  exit 1
fi
[[ -z "$(index_shape invalid_case)" ]]

create_table wrong_shape
sql wrong_shape -e "CREATE UNIQUE INDEX uq_bee_transaction_identity ON bee_transaction_log (transaction_id);"
if apply_migration wrong_shape >/dev/null 2>&1; then
  echo "wrong index shape unexpectedly succeeded" >&2
  exit 1
fi
[[ "$(index_shape wrong_shape)" == "0:transaction_id:FULL" ]]

create_table prefix_shape
sql prefix_shape -e "CREATE UNIQUE INDEX uq_bee_transaction_identity ON bee_transaction_log (test_id, transaction_id(1));
  INSERT INTO bee_transaction_log (test_id, transaction_id, price) VALUES (42, '42-1000-1', 100);"
if apply_migration prefix_shape >/dev/null 2>&1; then
  echo "prefix index shape unexpectedly succeeded" >&2
  exit 1
fi
[[ "$(index_shape prefix_shape)" == "0:test_id:FULL,transaction_id:1" ]]
[[ "$(sql --batch --skip-column-names prefix_shape -e "SELECT CONCAT(COUNT(*), ':', MIN(transaction_id), ':', MIN(price)) FROM bee_transaction_log;")" == "1:42-1000-1:100" ]]

create_table writer_case
sql -e "CREATE USER 'fixture'@'localhost'; GRANT ALL ON writer_case.* TO 'fixture'@'localhost';"
apply_migration writer_case
run_python_writer writer_case '42-1000-1' 100
run_php_writer writer_case '42-1000-2' 200
[[ "$(sql --batch --skip-column-names writer_case -e "SELECT CONCAT(COUNT(*), ':', GROUP_CONCAT(transaction_id ORDER BY transaction_id), ':', GROUP_CONCAT(price ORDER BY transaction_id)) FROM bee_transaction_log;")" == "2:42-1000-1,42-1000-2:100,200" ]]

echo "disposable MariaDB full-column identity and actual-writer migration: pass"
