-- +goose Up
CREATE TABLE message_threads (
    id BIGSERIAL PRIMARY KEY,
    created_by_user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    subject VARCHAR(255) NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT message_threads_subject_not_blank CHECK (length(btrim(subject)) > 0)
);

CREATE TABLE message_thread_participants (
    thread_id BIGINT NOT NULL REFERENCES message_threads(id) ON DELETE CASCADE,
    user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    joined_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    last_read_at TIMESTAMPTZ,
    archived_at TIMESTAMPTZ,
    PRIMARY KEY (thread_id, user_id)
);

CREATE TABLE messages (
    id BIGSERIAL PRIMARY KEY,
    thread_id BIGINT NOT NULL REFERENCES message_threads(id) ON DELETE CASCADE,
    sender_user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    body TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT messages_body_not_blank CHECK (length(btrim(body)) > 0)
);

CREATE INDEX idx_message_threads_created_by_user_id ON message_threads(created_by_user_id);
CREATE INDEX idx_message_threads_updated_at ON message_threads(updated_at DESC);
CREATE INDEX idx_message_thread_participants_user_id ON message_thread_participants(user_id);
CREATE INDEX idx_messages_thread_id_created_at ON messages(thread_id, created_at DESC);
CREATE INDEX idx_messages_sender_user_id ON messages(sender_user_id);

CREATE TRIGGER message_threads_updated_at BEFORE UPDATE ON message_threads
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

CREATE TRIGGER messages_updated_at BEFORE UPDATE ON messages
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- +goose Down
DROP TRIGGER IF EXISTS messages_updated_at ON messages;
DROP TRIGGER IF EXISTS message_threads_updated_at ON message_threads;

DROP TABLE IF EXISTS messages;
DROP TABLE IF EXISTS message_thread_participants;
DROP TABLE IF EXISTS message_threads;
