-- Миграция 001: таблица roblox_assets для кеширования assets Roblox CDN
--
-- Применяется к storys_db.
-- Запускать на S2 VM 117 (service-storys, primary PG).
-- При репликации S2 → S1 миграция доедет автоматически.

BEGIN;

CREATE TABLE IF NOT EXISTS roblox_assets (
    -- ID ассета в Roblox (числовой, из rbxassetid://<id>)
    rbx_asset_id    BIGINT       PRIMARY KEY,

    -- SHA256 сырого файла (после скачки с CDN, до конверта)
    -- Используется для второй дедупликации: разные rbx_asset_id могут указывать
    -- на одинаковый файл (Roblox делает редиректы).
    sha256_raw      CHAR(64)     NOT NULL,

    -- Тип ассета: 'mesh', 'texture', 'sound', 'csg', 'animation', 'video', 'unknown'
    asset_kind      VARCHAR(16)  NOT NULL,

    -- Content-Type как пришёл с CDN
    content_type    VARCHAR(64)  NOT NULL,

    -- Размер сырого файла
    raw_size_bytes  BIGINT       NOT NULL,

    -- Путь сырого файла в /opt/roblox-assets/raw/<sha256>.bin (или конкретное расширение)
    raw_path        TEXT         NOT NULL,

    -- Если делали конверт (mesh→glb, csg→glb) — путь и хеш конвертированного файла.
    -- Для остальных типов = NULL.
    converted_path  TEXT,
    converted_sha256 CHAR(64),
    converted_size_bytes BIGINT,

    -- URL по которому ассет реально отдаётся юзеру (https://assets.rublox.pro/...)
    public_url      TEXT         NOT NULL,

    -- Время первой скачки
    downloaded_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW(),

    -- Последнее использование (бампается при каждом импорте новой карты)
    last_used_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),

    -- Сколько карт использует этот ассет (для cleanup'а)
    refcount        INTEGER      NOT NULL DEFAULT 0,

    -- Метаданные конкретного типа (mesh: vertex count, texture: dimensions)
    metadata        JSONB        DEFAULT '{}'::jsonb,

    -- Failed reason если скачка/конверт упал
    error_msg       TEXT
);

CREATE INDEX IF NOT EXISTS idx_roblox_assets_sha256 ON roblox_assets(sha256_raw);
CREATE INDEX IF NOT EXISTS idx_roblox_assets_kind ON roblox_assets(asset_kind);
CREATE INDEX IF NOT EXISTS idx_roblox_assets_last_used ON roblox_assets(last_used_at);

-- Лог скачек по проектам (для отладки и tracking'а кто чем пользуется)
CREATE TABLE IF NOT EXISTS roblox_asset_usage (
    id              BIGSERIAL    PRIMARY KEY,
    project_id      INTEGER      NOT NULL,
    rbx_asset_id    BIGINT       NOT NULL REFERENCES roblox_assets(rbx_asset_id) ON DELETE CASCADE,
    created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    UNIQUE(project_id, rbx_asset_id)
);

CREATE INDEX IF NOT EXISTS idx_asset_usage_project ON roblox_asset_usage(project_id);

-- Лог импортов .rbxl (родительская запись для usage)
CREATE TABLE IF NOT EXISTS roblox_imports (
    id              BIGSERIAL    PRIMARY KEY,
    project_id      INTEGER,                                -- может быть NULL если ещё не создан
    user_id         INTEGER      NOT NULL,                  -- кто грузил (МИН только пока)
    rbxl_filename   TEXT         NOT NULL,
    rbxl_size       BIGINT       NOT NULL,
    rbxl_sha256     CHAR(64)     NOT NULL,
    instance_count  INTEGER,
    class_count     INTEGER,
    assets_total    INTEGER      DEFAULT 0,
    assets_failed   INTEGER      DEFAULT 0,
    status          VARCHAR(16)  NOT NULL DEFAULT 'pending',  -- pending/parsing/downloading/converting/done/failed
    error_msg       TEXT,
    started_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    finished_at     TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_imports_user ON roblox_imports(user_id);
CREATE INDEX IF NOT EXISTS idx_imports_status ON roblox_imports(status);

COMMIT;
