-- +goose Up

-- Generate UUID v7 (time-ordered, millisecond precision).
-- Structure: 48-bit unix_ts_ms | 4-bit version (0111) | 12-bit rand_a | 2-bit variant (10) | 62-bit rand_b
CREATE OR REPLACE FUNCTION uuid_generate_v7()
RETURNS uuid
AS $$
DECLARE
    unix_ts_ms bytea;
    uuid_bytes bytea;
BEGIN
    -- 48-bit Unix timestamp in milliseconds.
    -- int8send produces 8 big-endian bytes; skip the first 2 zero bytes to get 6.
    unix_ts_ms = substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3);

    -- Use a random v4 UUID as the source of random bits for rand_a and rand_b.
    uuid_bytes = uuid_send(gen_random_uuid());

    -- Overwrite bytes 0–5 with the timestamp (positions 1–6 in 1-indexed bytea).
    uuid_bytes = overlay(uuid_bytes placing unix_ts_ms from 1 for 6);

    -- Set version nibble (bits 48–51) to 0111 (7).
    uuid_bytes = set_bit(uuid_bytes, 48, 0);
    uuid_bytes = set_bit(uuid_bytes, 49, 1);
    uuid_bytes = set_bit(uuid_bytes, 50, 1);
    uuid_bytes = set_bit(uuid_bytes, 51, 1);

    -- Variant bits (64–65) stay at 10 as inherited from gen_random_uuid().

    RETURN encode(uuid_bytes, 'hex')::uuid;
END
$$ LANGUAGE plpgsql VOLATILE;

CREATE TYPE user_plan AS ENUM ('free', 'paid');
CREATE TYPE user_gender AS ENUM ('male', 'female');
CREATE TYPE user_goal AS ENUM ('lose', 'maintain', 'gain');
CREATE TYPE activity_level AS ENUM ('low', 'moderate', 'high');

CREATE TABLE users (
    id            UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
    firebase_uid  VARCHAR(128) NOT NULL UNIQUE,
    email         VARCHAR(255) NOT NULL,
    name          VARCHAR(255) NOT NULL DEFAULT '',
    avatar_url    TEXT,

    -- Body parameters
    height_cm     SMALLINT,
    weight_kg     DECIMAL(5,2),
    age           SMALLINT,
    gender        user_gender,
    activity      activity_level,

    -- Goal and calculated daily norm
    goal          user_goal,
    daily_calories INTEGER,

    -- Plan
    plan          user_plan NOT NULL DEFAULT 'free',

    -- Preferences (JSONB for flexibility)
    preferences   JSONB NOT NULL DEFAULT '{}'::jsonb,

    -- Refresh token
    refresh_token TEXT,
    token_expires_at TIMESTAMPTZ,

    created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_users_firebase_uid ON users (firebase_uid);
CREATE INDEX idx_users_email ON users (email);

-- +goose Down
DROP TABLE IF EXISTS users;
DROP TYPE IF EXISTS activity_level;
DROP TYPE IF EXISTS user_goal;
DROP TYPE IF EXISTS user_gender;
DROP TYPE IF EXISTS user_plan;
DROP FUNCTION IF EXISTS uuid_generate_v7();
