-- GHard Monitor: схема SQLite.
-- Время — UTC ISO-8601 (строки, лексикографически сортируются корректно).

CREATE TABLE IF NOT EXISTS servers (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    name        TEXT NOT NULL,                   -- отображаемое имя, задаётся в UI
    hostname    TEXT NOT NULL DEFAULT '',        -- как назвался агент
    os          TEXT NOT NULL DEFAULT '',
    kernel      TEXT NOT NULL DEFAULT '',
    ips_json    TEXT NOT NULL DEFAULT '[]',      -- адреса интерфейсов из пакета агента
    source_ip   TEXT NOT NULL DEFAULT '',        -- адрес входящего соединения
    note        TEXT NOT NULL DEFAULT '',        -- заметка: одна на сервер, edit в UI
    key_hash    TEXT NOT NULL UNIQUE,            -- sha256 ключа агента (plaintext нигде не храним)
    interval    INTEGER NOT NULL DEFAULT 30,     -- интервал агента, сек (для детекта offline)
    created_at  TEXT NOT NULL,
    last_seen   TEXT                             -- время последнего ingest (по часам panel)
);

CREATE TABLE IF NOT EXISTS metrics (
    id             INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id      INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    ts             TEXT NOT NULL,                -- timestamp пакета (агент или panel)
    cpu            REAL NOT NULL DEFAULT 0,     -- cpu, %
    load1          REAL NOT NULL DEFAULT 0,
    load5          REAL NOT NULL DEFAULT 0,
    load15         REAL NOT NULL DEFAULT 0,
    ram_used       INTEGER NOT NULL DEFAULT 0,
    ram_total      INTEGER NOT NULL DEFAULT 0,
    swap_used      INTEGER NOT NULL DEFAULT 0,
    swap_total     INTEGER NOT NULL DEFAULT 0,
    uptime         INTEGER NOT NULL DEFAULT 0,   -- сек
    net_in_mbs     REAL NOT NULL DEFAULT 0,      -- суммарный вход, МБ/с (panel считает по дельте)
    net_out_mbs    REAL NOT NULL DEFAULT 0,      -- суммарный выход, МБ/с
    disks_json     TEXT NOT NULL DEFAULT '[]',
    net_json       TEXT NOT NULL DEFAULT '[]',   -- сырые счётчики интерфейсов — для следующей дельты
    processes_json TEXT NOT NULL DEFAULT '[]',
    docker_json    TEXT NOT NULL DEFAULT '[]',
    extra_json     TEXT NOT NULL DEFAULT '{}'    -- temps, smart и прочее, что panel пока не разбирает
);

CREATE INDEX IF NOT EXISTS idx_metrics_server_ts ON metrics(server_id, ts);

CREATE TABLE IF NOT EXISTS events (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id    INTEGER REFERENCES servers(id) ON DELETE CASCADE,
    type         TEXT NOT NULL,                  -- cpu_high, server_offline, disk_added, ...
    severity     TEXT NOT NULL DEFAULT 'info',  -- info | warning | critical
    message      TEXT NOT NULL,
    data_json    TEXT NOT NULL DEFAULT '{}',
    ts           TEXT NOT NULL,
    acknowledged INTEGER NOT NULL DEFAULT 0
);

CREATE INDEX IF NOT EXISTS idx_events_server_ts ON events(server_id, ts);

-- Сетевые хранилища: шард-пути, примонтированные к машине с hard-panel.
-- Панель сама опрашивает их os.statvfs (share_samples.ok=0 — путь недоступен).
CREATE TABLE IF NOT EXISTS shares (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    name       TEXT NOT NULL,
    path       TEXT NOT NULL,
    created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS share_samples (
    id       INTEGER PRIMARY KEY AUTOINCREMENT,
    share_id INTEGER NOT NULL REFERENCES shares(id) ON DELETE CASCADE,
    ts       TEXT NOT NULL,
    total    INTEGER NOT NULL DEFAULT 0,     -- байты (statvfs f_blocks * f_frsize)
    used     INTEGER NOT NULL DEFAULT 0,     -- байты (total - f_bfree)
    ok       INTEGER NOT NULL DEFAULT 1      -- 1 = путь примонтирован и читается
);

CREATE INDEX IF NOT EXISTS idx_share_samples_share_ts ON share_samples(share_id, ts);

-- Health-чеки внешних сервисов (панель сама опрашивает их /health).
-- Формат отклика не договорён — прогрессивный минимум:
--   2xx → up; тело-JSON с строковым status: ok-набор → up,
--   degraded-набор → degraded, всё прочее → down;
--   не-2xx/таймаут/отказ → down (точка всё равно пишется).
CREATE TABLE IF NOT EXISTS services (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    name       TEXT NOT NULL,
    url        TEXT NOT NULL,      -- полный health URL сервиса
    created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS service_samples (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    service_id INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE,
    ts         TEXT NOT NULL,
    state      TEXT NOT NULL DEFAULT 'down',  -- up | degraded | down
    code       INTEGER,                       -- HTTP-код; NULL = сеть/таймаут/DNS
    latency_ms REAL NOT NULL DEFAULT 0,
    message    TEXT NOT NULL DEFAULT '',       -- status из тела или текст сетевой ошибки
    report     TEXT                            -- самосвидетельство (JSON §5 спеки; NULL = нет)
);

CREATE INDEX IF NOT EXISTS idx_service_samples_service_ts ON service_samples(service_id, ts);
-- Незавершённые OAuth-потоки gnexus-auth (state → pkce_verifier, 10 минут)
CREATE TABLE IF NOT EXISTS oauth_states (
    state          TEXT PRIMARY KEY,
    pkce_verifier  TEXT NOT NULL,
    return_to      TEXT NOT NULL DEFAULT '/',
    expires_at     TEXT NOT NULL
);

-- Браузерные сессии gnexus-auth (cookie ↔ профиль; TTL по expires_at)
CREATE TABLE IF NOT EXISTS sessions (
    id           TEXT PRIMARY KEY,
    user_id      TEXT NOT NULL,
    email        TEXT NOT NULL,
    display_name TEXT NOT NULL DEFAULT '',
    avatar_url   TEXT NOT NULL DEFAULT '',
    expires_at   TEXT NOT NULL,
    created_at   TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id);

-- Пользователи gnexus-auth: пер-сервисные настройки панели.
-- profile = словарь профиля verbatim (язык аккаунта — profile.locale);
-- locale  = override из настроек панели (NULL = следовать аккаунту).
-- Профиль живёт отдельно от сессий: сессии истекают/удаляются, настройка — нет.
CREATE TABLE IF NOT EXISTS users (
    user_id      TEXT PRIMARY KEY,          -- sub из gnexus-auth (= sessions.user_id)
    email        TEXT NOT NULL,
    display_name TEXT NOT NULL DEFAULT '',
    profile      TEXT NOT NULL DEFAULT '{}',  -- JSON профиля gnexus-auth verbatim
    locale       TEXT,                        -- override 'en'|'uk'|'ru'; NULL = авто
    created_at   TEXT NOT NULL,
    updated_at   TEXT NOT NULL
);
