/*
 This file is part of GNU Taler
 (C) 2023 Taler Systems S.A.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

// @ts-ignore: optional dependency
import type Database from "better-sqlite3";
import {
  ResultRow,
  Sqlite3Interface,
  Sqlite3Statement,
} from "./sqlite3-interface.js";

export async function createNodeSqlite3Impl(): Promise<Sqlite3Interface> {
  // @ts-ignore: optional dependency
  const bsq = (await import("better-sqlite3")).default;

  return {
    open(filename: string) {
      const internalDbHandle = bsq(filename);
      return {
        internalDbHandle,
        close() {
          internalDbHandle.close();
        },
        prepare(stmtStr): Sqlite3Statement {
          const stmtHandle = internalDbHandle.prepare(stmtStr);
          return {
            internalStatement: stmtHandle,
            getAll(params): ResultRow[] {
              let res: ResultRow[];
              if (params === undefined) {
                res = stmtHandle.all() as ResultRow[];
              } else {
                res = stmtHandle.all(params) as ResultRow[];
              }
              return res;
            },
            getFirst(params): ResultRow | undefined {
              let res: ResultRow | undefined;
              if (params === undefined) {
                res = stmtHandle.get() as ResultRow | undefined;
              } else {
                res = stmtHandle.get(params) as ResultRow | undefined;
              }
              return res;
            },
            run(params) {
              const myParams = [];
              if (params !== undefined) {
                myParams.push(params);
              }
              // The better-sqlite3 library doesn't like it we pass
              // undefined directly.
              let res: Database.RunResult;
              if (params !== undefined) {
                res = stmtHandle.run(params);
              } else {
                res = stmtHandle.run();
              }
              return {
                lastInsertRowid: res.lastInsertRowid,
              };
            },
          };
        },
        exec(sqlStr): void {
          internalDbHandle.exec(sqlStr);
        },
      };
    },
  };
}
