-- ─────────────────────────────────────────────────────────────────────────
-- CryptoWallet API — DB schema (idempotent)
-- Применить один раз на внешнюю БД при первом деплое.
-- Версия 3.0 (custodial: AES-GCM encrypted_mnemonic на сервере).
-- ─────────────────────────────────────────────────────────────────────────

-- ── USERS ────────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS users (
    id                  VARCHAR(26)   PRIMARY KEY,         -- ULID из JWT.sub
    email               VARCHAR(255)  NOT NULL UNIQUE,
    password_hash       VARCHAR(255)  NOT NULL,            -- "EXTERNAL_AUTH" (auth у BITOK)
    last_name           VARCHAR(255),
    first_name          VARCHAR(255),
    middle_name         VARCHAR(255),
    birth_date          DATE,
    crypto_wallet       VARCHAR(255),
    phone               VARCHAR(64),
    bik                 VARCHAR(64),
    account_number      VARCHAR(64),
    card_number         VARCHAR(64),
    inn                 VARCHAR(64),
    kyc_verified        BOOLEAN       NOT NULL DEFAULT FALSE,
    kyc_verified_at     TIMESTAMPTZ,
    is_deleted          BOOLEAN       NOT NULL DEFAULT FALSE,
    encrypted_vault     TEXT,                              -- legacy client-side AES blob (opt)
    vault_salt          VARCHAR(128),                      -- legacy client KDF salt (opt)
    encrypted_mnemonic  TEXT,                              -- AES-256-GCM blob (custodial)
    created_at          TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
    updated_at          TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

-- Добавляем encrypted_mnemonic если таблица существует с прошлой версии
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'users' AND column_name = 'encrypted_mnemonic'
    ) THEN
        ALTER TABLE users ADD COLUMN encrypted_mnemonic TEXT;
    END IF;
END $$;

-- CHECK: encrypted_mnemonic при значении должен иметь разумный размер.
-- AES-GCM blob: 12 IV + plaintext + 16 tag.
-- 12-word mnemonic ≈ 11*7 + 11 = 88 байт → 12+88+16 = 116 байт → ~156 base64 chars.
-- 24-word mnemonic ≈ 23*7 + 23 = 184 байт → 12+184+16 = 212 байт → ~284 base64 chars.
-- Минимум 140 (12 слов с маленькими словами), максимум 512 запас на 24 слова + padding.
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'users_encrypted_mnemonic_size'
    ) THEN
        ALTER TABLE users
            ADD CONSTRAINT users_encrypted_mnemonic_size
            CHECK (encrypted_mnemonic IS NULL OR (char_length(encrypted_mnemonic) BETWEEN 140 AND 512));
    END IF;
END $$;

-- ── WALLETS ──────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS wallets (
    id                  VARCHAR(26)   PRIMARY KEY,         -- ULID
    user_id             VARCHAR(26)   NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    chain               VARCHAR(16)   NOT NULL,            -- ETH / BTC / SOL / TRX / BSC
    address             VARCHAR(256)  NOT NULL,
    derivation_path     VARCHAR(64)   NOT NULL,
    created_at          TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
    UNIQUE (user_id, chain)
);

CREATE INDEX IF NOT EXISTS idx_wallets_user_id ON wallets(user_id);

-- ── SESSIONS (placeholder, не используется в текущей версии) ─────────────
CREATE TABLE IF NOT EXISTS sessions (
    id                  VARCHAR(26)   PRIMARY KEY,
    user_id             VARCHAR(26)   NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    expires_at          TIMESTAMPTZ   NOT NULL,
    created_at          TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

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