"""SQLite FTS5 schema constants and SQL statements for the signal search index."""

from __future__ import annotations

_SCHEMA_RAW = """\
CREATE TABLE IF NOT EXISTS signals_raw (
    id                    INTEGER PRIMARY KEY,
    type                  TEXT,
    signal_name           TEXT,
    frame_name            TEXT,
    frame_id              TEXT,
    namespace             TEXT,
    description           TEXT,
    unit                  TEXT,
    senders               TEXT,
    receivers             TEXT,
    named_values          TEXT,
    named_values_json     TEXT,
    min                   REAL,
    max                   REAL,
    factor                REAL,
    "offset"              REAL,
    cycle_time            REAL,
    start_value           REAL,
    size                  INTEGER,
    is_raw                INTEGER,
    source                TEXT DEFAULT 'grpc',
    channel               TEXT,
    channel_type              TEXT,
    file_path             TEXT,
    workspace_path        TEXT,
    start_bit             INTEGER,
    is_big_endian         INTEGER,
    is_signed             INTEGER,
    is_ieee_floating_type INTEGER,
    multiplex_json        TEXT,
    payload_size          INTEGER,
    opt_empty_payload     TEXT,
    is_can_fd             INTEGER,
    is_extended           INTEGER,
    can_fd_flags          INTEGER,
    multiplex_selector    TEXT,
    e2e_json              TEXT,
    secoc_json            TEXT,
    groups_json           TEXT,
    channel_cluster       TEXT,
    channel_physical_name TEXT
)"""

# FTS column list must match _FIELD_DEFINITIONS in query.py, which is the single source of truth.
_SCHEMA_FTS = """\
CREATE VIRTUAL TABLE IF NOT EXISTS signals_fts USING fts5(
    signal_name, frame_name, frame_id, namespace, channel,
    description,
    unit, senders, receivers, named_values,
    content='signals_raw', content_rowid='id',
    tokenize="unicode61 tokenchars '_-'"
)"""

_TRIGGERS = [
    """\
CREATE TRIGGER IF NOT EXISTS signals_ai AFTER INSERT ON signals_raw BEGIN
    INSERT INTO signals_fts(rowid, signal_name, frame_name, frame_id, namespace, channel,
        description, unit, senders, receivers, named_values)
    VALUES (new.id, new.signal_name, new.frame_name, new.frame_id, new.namespace, new.channel,
        new.description, new.unit, new.senders,
        new.receivers, new.named_values);
END""",
    """\
CREATE TRIGGER IF NOT EXISTS signals_ad AFTER DELETE ON signals_raw BEGIN
    INSERT INTO signals_fts(signals_fts, rowid, signal_name, frame_name, frame_id, namespace, channel,
        description, unit, senders, receivers, named_values)
    VALUES ('delete', old.id, old.signal_name, old.frame_name, old.frame_id, old.namespace, old.channel,
        old.description, old.unit, old.senders,
        old.receivers, old.named_values);
END""",
]

_INSERT_SQL = """\
INSERT INTO signals_raw (
    type, signal_name, frame_name, frame_id, namespace,
    description, unit, senders, receivers, named_values,
    named_values_json, min, max, factor, "offset", cycle_time, start_value, size,
    is_raw, source, channel, channel_type, file_path, workspace_path,
    start_bit, is_big_endian, is_signed, is_ieee_floating_type, multiplex_json,
    payload_size, opt_empty_payload, is_can_fd, is_extended, can_fd_flags,
    multiplex_selector, e2e_json, secoc_json, groups_json,
    channel_cluster, channel_physical_name
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"""

# Applied at connect() time to upgrade existing databases that predate these columns.
_MIGRATION_SQL = [
    "ALTER TABLE signals_raw ADD COLUMN channel TEXT",
    "ALTER TABLE signals_raw ADD COLUMN channel_type TEXT",
    "ALTER TABLE signals_raw ADD COLUMN file_path TEXT",
    "ALTER TABLE signals_raw ADD COLUMN named_values_json TEXT",
    "ALTER TABLE signals_raw ADD COLUMN start_bit INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN is_big_endian INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN is_signed INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN is_ieee_floating_type INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN multiplex_json TEXT",
    "ALTER TABLE signals_raw ADD COLUMN payload_size INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN opt_empty_payload TEXT",
    "ALTER TABLE signals_raw ADD COLUMN is_can_fd INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN is_extended INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN can_fd_flags INTEGER",
    "ALTER TABLE signals_raw ADD COLUMN multiplex_selector TEXT",
    "ALTER TABLE signals_raw ADD COLUMN e2e_json TEXT",
    "ALTER TABLE signals_raw ADD COLUMN secoc_json TEXT",
    "ALTER TABLE signals_raw ADD COLUMN groups_json TEXT",
    "ALTER TABLE signals_raw ADD COLUMN channel_cluster TEXT",
    "ALTER TABLE signals_raw ADD COLUMN channel_physical_name TEXT",
    "ALTER TABLE signals_raw ADD COLUMN workspace_path TEXT",
    "ALTER TABLE signals_raw ADD COLUMN signal_name TEXT",
]

_SCHEMA_TOKENS = """\
CREATE TABLE IF NOT EXISTS signals_tokens (
    signal_id INTEGER NOT NULL,
    field      TEXT    NOT NULL,
    token      TEXT    NOT NULL
)"""

_SCHEMA_TOKENS_INDEX = """\
CREATE INDEX IF NOT EXISTS idx_tokens_field_token
ON signals_tokens(field, token, signal_id)"""

_INSERT_TOKEN_SQL = "INSERT INTO signals_tokens (signal_id, field, token) VALUES (?, ?, ?)"

_TOKENIZED_SUGGEST_FIELDS = frozenset({"signal_name", "frame_name", "description", "receivers", "senders", "named_values"})

# Fields whose values contain dot-separated parts that should each become a separate suggest token.
_DOT_SPLIT_FIELDS = frozenset({"signal_name", "frame_name"})
