-- Warehouse layer: dimensional model
-- Idempotent: all CREATE TABLE IF NOT EXISTS

CREATE SCHEMA IF NOT EXISTS warehouse;

-- ── Dimension: Dates ────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS warehouse.dim_dates (
    date_id         DATE PRIMARY KEY,
    year            SMALLINT    NOT NULL,
    quarter         SMALLINT    NOT NULL,
    month           SMALLINT    NOT NULL,
    month_name      TEXT        NOT NULL,
    week            SMALLINT    NOT NULL,
    day_of_week     SMALLINT    NOT NULL,   -- 0=Mon, 6=Sun
    day_name        TEXT        NOT NULL,
    is_weekend      BOOLEAN     NOT NULL,
    is_month_end    BOOLEAN     NOT NULL
);

-- ── Dimension: Customers ────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS warehouse.dim_customers (
    customer_key        SERIAL PRIMARY KEY,
    customer_id         TEXT UNIQUE NOT NULL,   -- from stg_customers (order-level id)
    customer_unique_id  TEXT NOT NULL,
    zip_code_prefix     TEXT,
    city                TEXT,
    state               TEXT,
    lat                 DOUBLE PRECISION,
    lng                 DOUBLE PRECISION,
    first_order_date    DATE,
    last_order_date     DATE,
    total_orders        INTEGER         DEFAULT 0,
    total_revenue       NUMERIC(12, 2)  DEFAULT 0,
    clv_score           NUMERIC(10, 4),
    rfm_segment         TEXT,           -- e.g. "Champions", "At Risk"
    churn_probability   NUMERIC(5, 4),
    segment_label       INTEGER,        -- KMeans cluster id
    _updated_at         TIMESTAMPTZ     DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_dim_customers_unique_id ON warehouse.dim_customers(customer_unique_id);
CREATE INDEX IF NOT EXISTS idx_dim_customers_state ON warehouse.dim_customers(state);
CREATE INDEX IF NOT EXISTS idx_dim_customers_segment ON warehouse.dim_customers(rfm_segment);

-- ── Dimension: Products ─────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS warehouse.dim_products (
    product_key         SERIAL PRIMARY KEY,
    product_id          TEXT UNIQUE NOT NULL,
    category_name_pt    TEXT,
    category_name_en    TEXT,
    weight_g            INTEGER,
    length_cm           INTEGER,
    height_cm           INTEGER,
    width_cm            INTEGER,
    _updated_at         TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_dim_products_category ON warehouse.dim_products(category_name_en);

-- ── Dimension: Sellers ──────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS warehouse.dim_sellers (
    seller_key          SERIAL PRIMARY KEY,
    seller_id           TEXT UNIQUE NOT NULL,
    zip_code_prefix     TEXT,
    city                TEXT,
    state               TEXT,
    lat                 DOUBLE PRECISION,
    lng                 DOUBLE PRECISION,
    total_orders        INTEGER         DEFAULT 0,
    avg_review_score    NUMERIC(3, 2),
    on_time_rate        NUMERIC(5, 4),
    _updated_at         TIMESTAMPTZ     DEFAULT now()
);

-- ── Fact Table: Orders (grain = 1 row per order_item) ──────────────────────
CREATE TABLE IF NOT EXISTS warehouse.fact_orders (
    fact_key                BIGSERIAL PRIMARY KEY,
    order_id                TEXT        NOT NULL,
    order_item_id           SMALLINT    NOT NULL,
    customer_key            INTEGER     REFERENCES warehouse.dim_customers(customer_key),
    product_key             INTEGER     REFERENCES warehouse.dim_products(product_key),
    seller_key              INTEGER     REFERENCES warehouse.dim_sellers(seller_key),
    order_date_id           DATE        REFERENCES warehouse.dim_dates(date_id),
    approved_date_id        DATE,
    delivered_date_id       DATE,
    estimated_delivery_id   DATE,
    order_status            TEXT,
    price                   NUMERIC(10, 2),
    freight_value           NUMERIC(10, 2),
    payment_value           NUMERIC(10, 2),
    payment_type            TEXT,
    payment_installments    SMALLINT,
    review_score            SMALLINT,
    days_to_delivery        INTEGER,        -- delivered_date - approved_date
    delivery_delay_days     INTEGER,        -- delivered_date - estimated_date (neg = early)
    is_late                 BOOLEAN,
    UNIQUE(order_id, order_item_id)
);

CREATE INDEX IF NOT EXISTS idx_fact_orders_customer ON warehouse.fact_orders(customer_key);
CREATE INDEX IF NOT EXISTS idx_fact_orders_date ON warehouse.fact_orders(order_date_id);
CREATE INDEX IF NOT EXISTS idx_fact_orders_seller ON warehouse.fact_orders(seller_key);
CREATE INDEX IF NOT EXISTS idx_fact_orders_product ON warehouse.fact_orders(product_key);
CREATE INDEX IF NOT EXISTS idx_fact_orders_status ON warehouse.fact_orders(order_status);
