CREATE DATABASE IF NOT EXISTS encrypted_chat
  CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE encrypted_chat;

-- Users: identity_key is Ed25519 (32B), rsa_public_key for login challenge only
CREATE TABLE IF NOT EXISTS users (
    id CHAR(36) NOT NULL PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    rsa_public_key TEXT NOT NULL,
    identity_key BLOB NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Devices: each user can have multiple devices
CREATE TABLE IF NOT EXISTS devices (
    id CHAR(36) NOT NULL PRIMARY KEY,
    user_id CHAR(36) NOT NULL,
    device_name VARCHAR(255) DEFAULT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_seen_at DATETIME DEFAULT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_devices_user (user_id)
) ENGINE=InnoDB;

-- Signed Pre-Keys (X25519, signed by Ed25519 identity key) — per device
CREATE TABLE IF NOT EXISTS signed_prekeys (
    id CHAR(36) NOT NULL PRIMARY KEY,
    user_id CHAR(36) NOT NULL,
    device_id CHAR(36) DEFAULT NULL,
    public_key BLOB NOT NULL,
    signature BLOB NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_spk_user_device (user_id, device_id)
) ENGINE=InnoDB;

-- One-Time Pre-Keys (consumed on use) — per device
CREATE TABLE IF NOT EXISTS one_time_prekeys (
    id CHAR(36) NOT NULL PRIMARY KEY,
    user_id CHAR(36) NOT NULL,
    device_id CHAR(36) DEFAULT NULL,
    public_key BLOB NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_opk_user_device (user_id, device_id)
) ENGINE=InnoDB;

-- Conversations
CREATE TABLE IF NOT EXISTS conversations (
    id CHAR(36) NOT NULL PRIMARY KEY,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    name VARCHAR(255) DEFAULT NULL,
    created_by CHAR(36) DEFAULT NULL,
    avatar_file VARCHAR(255) DEFAULT NULL
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS conversation_members (
    conversation_id CHAR(36) NOT NULL,
    user_id CHAR(36) NOT NULL,
    joined_at DATETIME NULL,
    PRIMARY KEY (conversation_id, user_id),
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_cm_user (user_id)
) ENGINE=InnoDB;

-- Group invitations (pending invitations to join a group)
CREATE TABLE IF NOT EXISTS group_invitations (
    id CHAR(36) NOT NULL PRIMARY KEY,
    conversation_id CHAR(36) NOT NULL,
    user_id CHAR(36) NOT NULL,
    invited_by CHAR(36) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uq_conv_user (conversation_id, user_id),
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (invited_by) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_inv_user (user_id)
) ENGINE=InnoDB;

-- Messages: per-recipient ciphertext (Double Ratchet = each recipient has different ciphertext)
CREATE TABLE IF NOT EXISTS messages (
    id CHAR(36) NOT NULL PRIMARY KEY,
    conversation_id CHAR(36) NOT NULL,
    sender_id CHAR(36) NOT NULL,
    sender_device_id CHAR(36) DEFAULT NULL,
    ratchet_header BLOB NOT NULL,
    x3dh_header BLOB DEFAULT NULL,
    sender_chain_id BLOB DEFAULT NULL,
    sender_chain_n INT DEFAULT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at DATETIME DEFAULT NULL,
    image_file_id CHAR(36) DEFAULT NULL,
    pinned_at DATETIME DEFAULT NULL,
    pinned_by CHAR(36) DEFAULT NULL,
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_messages_conv_created (conversation_id, created_at),
    INDEX idx_messages_deleted (conversation_id, deleted_at),
    INDEX idx_messages_pinned (conversation_id, pinned_at)
) ENGINE=InnoDB;

-- Per-recipient encrypted content — per device
-- device_id '00000000-0000-0000-0000-000000000000' = self-encrypted / legacy
CREATE TABLE IF NOT EXISTS message_recipients (
    message_id CHAR(36) NOT NULL,
    user_id CHAR(36) NOT NULL,
    device_id CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
    encrypted_content BLOB NOT NULL,
    nonce BLOB NOT NULL,
    ratchet_header BLOB DEFAULT NULL,
    x3dh_header BLOB DEFAULT NULL,
    PRIMARY KEY (message_id, user_id, device_id),
    FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;

-- Sender Keys for groups (distributed via pairwise ratchet) — per device
CREATE TABLE IF NOT EXISTS group_sender_keys (
    conversation_id CHAR(36) NOT NULL,
    sender_id CHAR(36) NOT NULL,
    device_id CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
    chain_id BLOB NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (conversation_id, sender_id, device_id),
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;

-- Read receipts
CREATE TABLE IF NOT EXISTS message_reads (
    message_id CHAR(36) NOT NULL,
    user_id CHAR(36) NOT NULL,
    read_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (message_id, user_id),
    FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_reads_user (user_id),
    INDEX idx_reads_read_at (read_at)
) ENGINE=InnoDB;

-- Delivery receipts
CREATE TABLE IF NOT EXISTS message_deliveries (
    message_id CHAR(36) NOT NULL,
    user_id    CHAR(36) NOT NULL,
    delivered_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (message_id, user_id),
    FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id)    REFERENCES users(id)    ON DELETE CASCADE
) ENGINE=InnoDB;

-- User profiles
CREATE TABLE IF NOT EXISTS user_profiles (
    user_id CHAR(36) NOT NULL PRIMARY KEY,
    phone VARCHAR(50) DEFAULT NULL,
    phone_visible TINYINT(1) NOT NULL DEFAULT 0,
    email_visible TINYINT(1) NOT NULL DEFAULT 1,
    location VARCHAR(255) DEFAULT NULL,
    location_visible TINYINT(1) NOT NULL DEFAULT 0,
    avatar_file VARCHAR(255) DEFAULT NULL,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;

-- Message reactions (emoji reactions on messages)
CREATE TABLE IF NOT EXISTS message_reactions (
    id CHAR(36) NOT NULL PRIMARY KEY,
    message_id CHAR(36) NOT NULL,
    user_id CHAR(36) NOT NULL,
    reaction VARCHAR(32) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uq_reaction (message_id, user_id),
    FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_reactions_created_at (created_at)
) ENGINE=InnoDB;

-- Image uploads
CREATE TABLE IF NOT EXISTS image_uploads (
    file_id CHAR(36) NOT NULL PRIMARY KEY,
    conversation_id CHAR(36) NOT NULL,
    uploader_id CHAR(36) NOT NULL,
    file_size BIGINT NOT NULL DEFAULT 0,
    completed BOOLEAN NOT NULL DEFAULT FALSE,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (uploader_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
