CREATE TABLE IF NOT EXISTS users (
    id            INTEGER PRIMARY KEY AUTOINCREMENT,
    username      TEXT    NOT NULL UNIQUE,
    password_hash TEXT    NOT NULL,
    role          TEXT    NOT NULL DEFAULT 'viewer',
    created_at    TEXT    NOT NULL DEFAULT (datetime('now')),
    last_login    TEXT,
    CHECK (role IN ('admin', 'viewer'))
);

CREATE TABLE IF NOT EXISTS servers (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    name            TEXT    NOT NULL,
    description     TEXT,
    game_type       TEXT    NOT NULL DEFAULT 'arma3',
    status          TEXT    NOT NULL DEFAULT 'stopped',
    pid             INTEGER,
    exe_path        TEXT    NOT NULL,
    started_at      TEXT,
    stopped_at      TEXT,
    game_port       INTEGER NOT NULL,
    rcon_port       INTEGER,
    auto_restart    INTEGER NOT NULL DEFAULT 0,
    max_restarts    INTEGER NOT NULL DEFAULT 3,
    restart_window_seconds INTEGER NOT NULL DEFAULT 300,
    restart_count   INTEGER NOT NULL DEFAULT 0,
    last_restart_at TEXT,
    created_at      TEXT    NOT NULL DEFAULT (datetime('now')),
    updated_at      TEXT    NOT NULL DEFAULT (datetime('now')),
    CHECK (status IN ('stopped','starting','running','stopping','crashed','error')),
    CHECK (game_port BETWEEN 1024 AND 65535),
    CHECK (rcon_port IS NULL OR (rcon_port BETWEEN 1024 AND 65535))
);

CREATE INDEX IF NOT EXISTS idx_servers_status    ON servers(status);
CREATE INDEX IF NOT EXISTS idx_servers_game_type ON servers(game_type);
CREATE INDEX IF NOT EXISTS idx_servers_game_port ON servers(game_port);

CREATE TABLE IF NOT EXISTS game_configs (
    id             INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id      INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    game_type      TEXT    NOT NULL,
    section        TEXT    NOT NULL,
    config_json    TEXT    NOT NULL DEFAULT '{}',
    config_version INTEGER NOT NULL DEFAULT 1,
    schema_version TEXT    NOT NULL DEFAULT '1.0.0',
    updated_at     TEXT    NOT NULL DEFAULT (datetime('now')),
    UNIQUE(server_id, section)
);

CREATE INDEX IF NOT EXISTS idx_game_configs_server       ON game_configs(server_id);
CREATE INDEX IF NOT EXISTS idx_game_configs_type_section ON game_configs(game_type, section);

CREATE TABLE IF NOT EXISTS mods (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    game_type    TEXT    NOT NULL,
    name         TEXT    NOT NULL,
    folder_path  TEXT    NOT NULL,
    workshop_id  TEXT,
    description  TEXT,
    game_data    TEXT    DEFAULT '{}',
    created_at   TEXT    NOT NULL DEFAULT (datetime('now')),
    UNIQUE (game_type, folder_path)
);

CREATE TABLE IF NOT EXISTS server_mods (
    server_id    INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    mod_id       INTEGER NOT NULL REFERENCES mods(id) ON DELETE CASCADE,
    is_server_mod INTEGER NOT NULL DEFAULT 0,
    sort_order   INTEGER NOT NULL DEFAULT 0,
    game_data    TEXT    DEFAULT '{}',
    PRIMARY KEY (server_id, mod_id)
);

CREATE INDEX IF NOT EXISTS idx_server_mods_server ON server_mods(server_id);

CREATE TABLE IF NOT EXISTS missions (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id    INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    filename     TEXT    NOT NULL,
    mission_name TEXT    NOT NULL,
    terrain      TEXT,
    file_size    INTEGER,
    game_data    TEXT    DEFAULT '{}',
    uploaded_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    UNIQUE (server_id, filename)
);

CREATE INDEX IF NOT EXISTS idx_missions_server ON missions(server_id);

CREATE TABLE IF NOT EXISTS mission_rotation (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id   INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    mission_id  INTEGER NOT NULL REFERENCES missions(id) ON DELETE CASCADE,
    sort_order  INTEGER NOT NULL DEFAULT 0,
    difficulty  TEXT,
    params_json TEXT    NOT NULL DEFAULT '{}',
    game_data   TEXT    DEFAULT '{}',
    UNIQUE (server_id, sort_order)
);

CREATE INDEX IF NOT EXISTS idx_mission_rotation_server ON mission_rotation(server_id);

CREATE TABLE IF NOT EXISTS players (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id   INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    slot_id     TEXT    NOT NULL,
    name        TEXT    NOT NULL,
    guid        TEXT,
    ip          TEXT,
    ping        INTEGER,
    game_data   TEXT    DEFAULT '{}',
    joined_at   TEXT    NOT NULL DEFAULT (datetime('now')),
    updated_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    UNIQUE (server_id, slot_id)
);

CREATE INDEX IF NOT EXISTS idx_players_server ON players(server_id);

CREATE TABLE IF NOT EXISTS player_history (
    id               INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id        INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    name             TEXT    NOT NULL,
    guid             TEXT,
    ip               TEXT,
    game_data        TEXT    DEFAULT '{}',
    joined_at        TEXT    NOT NULL,
    left_at          TEXT    NOT NULL DEFAULT (datetime('now')),
    session_duration_seconds INTEGER
);

CREATE INDEX IF NOT EXISTS idx_player_history_server ON player_history(server_id);
CREATE INDEX IF NOT EXISTS idx_player_history_guid   ON player_history(guid);

CREATE TABLE IF NOT EXISTS bans (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id   INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    guid        TEXT,
    name        TEXT,
    reason      TEXT,
    banned_by   TEXT,
    banned_at   TEXT    NOT NULL DEFAULT (datetime('now')),
    expires_at  TEXT,
    is_active   INTEGER NOT NULL DEFAULT 1,
    game_data   TEXT    DEFAULT '{}',
    CHECK (is_active IN (0, 1))
);

CREATE INDEX IF NOT EXISTS idx_bans_server ON bans(server_id);
CREATE INDEX IF NOT EXISTS idx_bans_guid   ON bans(guid);
CREATE INDEX IF NOT EXISTS idx_bans_active ON bans(is_active);

CREATE TABLE IF NOT EXISTS logs (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id   INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    timestamp   TEXT    NOT NULL,
    level       TEXT    NOT NULL DEFAULT 'info',
    message     TEXT    NOT NULL,
    created_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    CHECK (level IN ('info', 'warning', 'error'))
);

CREATE INDEX IF NOT EXISTS idx_logs_server_ts ON logs(server_id, timestamp);
CREATE INDEX IF NOT EXISTS idx_logs_level     ON logs(level);
CREATE INDEX IF NOT EXISTS idx_logs_created   ON logs(created_at);

CREATE TABLE IF NOT EXISTS metrics (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id    INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    timestamp    TEXT    NOT NULL DEFAULT (datetime('now')),
    cpu_percent  REAL,
    ram_mb       REAL,
    player_count INTEGER
);

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

CREATE TABLE IF NOT EXISTS server_events (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    server_id   INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
    event_type  TEXT    NOT NULL,
    actor       TEXT,
    detail      TEXT,
    created_at  TEXT    NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX IF NOT EXISTS idx_events_server ON server_events(server_id, created_at)