#!/usr/bin/env python3

import argparse
import os
import re
import subprocess

SCHEMA_PATH = "SignalServiceKit/Resources/schema.sql"

TABLES_TO_IGNORE = [
    "grdb_migrations",
    "sqlite_sequence",
    "indexable_text_fts_data",
    "indexable_text_fts_idx",
    "indexable_text_fts_docsize",
    "indexable_text_fts_config",
    "SearchableNameFTS_data",
    "SearchableNameFTS_idx",
    "SearchableNameFTS_docsize",
    "SearchableNameFTS_config",
]


def main(ns):
    repo_root = os.path.abspath(os.path.join(__file__, "../.."))
    args = ["Scripts/sqlclient", "--quiet"]
    if ns.staging:
        args.extend(["--staging"])
    if ns.path is not None:
        args.extend(["--path", ns.path])
    if ns.passphrase is not None:
        args.extend(["--passphrase", ns.passphrase])
    args.extend(["--", ".schema"])
    schema = subprocess.run(
        args,
        check=True,
        encoding="utf8",
        capture_output=True,
        cwd=repo_root,
    ).stdout

    # Drop the "ok" from setting the passphrase.
    assert schema.startswith("ok\n")
    schema = schema[3:]

    # Normalize the formatting.
    schema = subprocess.run(
        ["bundle", "exec", "anbt-sql-formatter"],
        check=True,
        input=schema,
        encoding="utf8",
        capture_output=True,
    ).stdout

    # Remove tables that don't need to be included. (Generally, some other
    # mechanism creates these so that we don't need to.)
    for table in TABLES_TO_IGNORE:
        schema = re.sub(
            r"CREATE\s+TABLE\s+(IF NOT EXISTS\s+)?'?" + table + r".*?;\n\n",
            "",
            schema,
            flags=re.MULTILINE | re.DOTALL,
        )

    file_path = os.path.join(repo_root, SCHEMA_PATH)
    with open(file_path, "r") as file:
        old_schema = file.read()

    if schema == old_schema:
        return

    with open(file_path, "w") as file:
        file.write(schema)


def parse_args():
    parser = argparse.ArgumentParser()
    target = parser.add_mutually_exclusive_group()
    target.add_argument(
        "--staging",
        action="store_true",
        help="Target the staging database of the currently-booted simulator.",
    )
    target.add_argument(
        "--path",
        metavar="/a/b/c",
        help="Target the database at the provided path.",
    )
    parser.add_argument(
        "--passphrase",
        metavar="abcdef0123456789",
        help="Use the provided passphrase to decrypt the database. "
        "(Or you can use “Settings” -> “Internal” -> “Misc” -> “Save plaintext database key”.)",
    )
    return parser.parse_args()


if __name__ == "__main__":
    ns = parse_args()
    main(ns)
