-- =============================================================================
-- HOTEL RESERVATIONS — DATA MART (STAR SCHEMA)
-- Target: Oracle (university lab schema)
-- Based on A.24 Revenue Data Mart — Dimensional Modelling by Example
-- =============================================================================

-- -----------------------------------------------------------------------------
-- DIMENSION TABLES
-- -----------------------------------------------------------------------------

-- YYYYMMDD integer key — cheap date range predicates, no JOIN to calendar needed
CREATE TABLE DIM_DATE (
    date_key        NUMBER(8,0)         NOT NULL,
    full_date       DATE                NOT NULL,
    year            NUMBER(4,0)         NOT NULL,
    quarter         NUMBER(1,0)         NOT NULL,
    month           NUMBER(2,0)         NOT NULL,
    month_name      VARCHAR2(10)        NOT NULL,
    week_number     NUMBER(2,0)         NOT NULL,
    day_of_month    NUMBER(2,0)         NOT NULL,
    day_name        VARCHAR2(10)        NOT NULL,
    is_weekend      NUMBER(1,0)         NOT NULL,
    is_business_day NUMBER(1,0)         NOT NULL,
    season          VARCHAR2(10)        NOT NULL,    -- Peak / High / Low / Off
    CONSTRAINT pk_dim_date      PRIMARY KEY (date_key),
    CONSTRAINT ck_dim_date_wknd CHECK (is_weekend      IN (0,1)),
    CONSTRAINT ck_dim_date_bday CHECK (is_business_day IN (0,1))
);

CREATE TABLE DIM_COUNTRY (
    country_key NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    country_id  NUMBER(10,0)    NOT NULL,
    code        CHAR(2)         NOT NULL,
    name        VARCHAR2(100)   NOT NULL,
    currency    VARCHAR2(10)    NOT NULL,
    CONSTRAINT pk_dim_country   PRIMARY KEY (country_key),
    CONSTRAINT uq_dim_cntry_id  UNIQUE (country_id)
);

CREATE TABLE DIM_STAR_RATING (
    star_rating_key NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    star_rating_id  NUMBER(10,0)    NOT NULL,
    code            NUMBER(1,0)     NOT NULL,
    description     VARCHAR2(20)    NOT NULL,
    CONSTRAINT pk_dim_star      PRIMARY KEY (star_rating_key),
    CONSTRAINT uq_dim_star_id   UNIQUE (star_rating_id)
);

CREATE TABLE DIM_HOTEL_CHAIN (
    hotel_chain_key NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    hotel_chain_id  NUMBER(10,0)    NOT NULL,
    code            VARCHAR2(10)    NOT NULL,
    name            VARCHAR2(100)   NOT NULL,
    CONSTRAINT pk_dim_chain     PRIMARY KEY (hotel_chain_key),
    CONSTRAINT uq_dim_chain_id  UNIQUE (hotel_chain_id)
);

CREATE TABLE DIM_HOTEL (
    hotel_key           NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    hotel_id            NUMBER(10,0)    NOT NULL,
    hotel_chain_key     NUMBER(10,0),
    country_key         NUMBER(10,0)    NOT NULL,
    star_rating_key     NUMBER(10,0)    NOT NULL,
    code                VARCHAR2(20)    NOT NULL,
    name                VARCHAR2(150)   NOT NULL,
    city                VARCHAR2(100)   NOT NULL,
    CONSTRAINT pk_dim_hotel         PRIMARY KEY (hotel_key),
    CONSTRAINT uq_dim_hotel_id      UNIQUE (hotel_id),
    CONSTRAINT fk_dh_chain          FOREIGN KEY (hotel_chain_key) REFERENCES DIM_HOTEL_CHAIN (hotel_chain_key),
    CONSTRAINT fk_dh_country        FOREIGN KEY (country_key)     REFERENCES DIM_COUNTRY     (country_key),
    CONSTRAINT fk_dh_star           FOREIGN KEY (star_rating_key) REFERENCES DIM_STAR_RATING (star_rating_key)
);

CREATE TABLE DIM_ROOM (
    room_key        NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    room_id         NUMBER(10,0)    NOT NULL,
    hotel_key       NUMBER(10,0)    NOT NULL,
    room_number     VARCHAR2(10)    NOT NULL,
    floor           NUMBER(3,0)     NOT NULL,
    room_type_code  VARCHAR2(20)    NOT NULL,
    room_type_desc  VARCHAR2(100)   NOT NULL,
    smoking_yn      NUMBER(1,0)     NOT NULL,
    standard_rate   NUMBER(10,2)    NOT NULL,
    CONSTRAINT pk_dim_room      PRIMARY KEY (room_key),
    CONSTRAINT uq_dim_room_id   UNIQUE (room_id),
    CONSTRAINT fk_dr_hotel      FOREIGN KEY (hotel_key) REFERENCES DIM_HOTEL (hotel_key),
    CONSTRAINT ck_dim_room_smk  CHECK (smoking_yn IN (0,1))
);

CREATE TABLE DIM_GUEST (
    guest_key   NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    guest_id    NUMBER(10,0)    NOT NULL,
    country_key NUMBER(10,0),
    name        VARCHAR2(150)   NOT NULL,
    city        VARCHAR2(100),
    CONSTRAINT pk_dim_guest     PRIMARY KEY (guest_key),
    CONSTRAINT uq_dim_guest_id  UNIQUE (guest_id),
    CONSTRAINT fk_dg_country    FOREIGN KEY (country_key) REFERENCES DIM_COUNTRY (country_key)
);

-- -----------------------------------------------------------------------------
-- FACT TABLE
-- -----------------------------------------------------------------------------

-- Grain: one row per room_booking
-- Revenue measures: nightly_rate, total_amount, nights_stayed
CREATE TABLE FACT_ROOM_BOOKING (
    fact_id             NUMBER(10,0)    GENERATED ALWAYS AS IDENTITY,
    -- foreign keys
    hotel_key           NUMBER(10,0)    NOT NULL,
    hotel_chain_key     NUMBER(10,0),
    room_key            NUMBER(10,0)    NOT NULL,
    guest_key           NUMBER(10,0)    NOT NULL,
    country_key         NUMBER(10,0),
    star_rating_key     NUMBER(10,0)    NOT NULL,
    checkin_date_key    NUMBER(8,0)     NOT NULL,
    checkout_date_key   NUMBER(8,0)     NOT NULL,
    -- degenerate dimensions
    booking_status      VARCHAR2(20)    NOT NULL,
    -- measures
    nights_stayed       NUMBER(4,0)     NOT NULL,
    nightly_rate        NUMBER(10,2)    NOT NULL,
    total_amount        NUMBER(12,2)    NOT NULL,
    CONSTRAINT pk_fact_rb       PRIMARY KEY (fact_id),
    CONSTRAINT fk_frb_hotel     FOREIGN KEY (hotel_key)        REFERENCES DIM_HOTEL       (hotel_key),
    CONSTRAINT fk_frb_chain     FOREIGN KEY (hotel_chain_key)  REFERENCES DIM_HOTEL_CHAIN (hotel_chain_key),
    CONSTRAINT fk_frb_room      FOREIGN KEY (room_key)         REFERENCES DIM_ROOM        (room_key),
    CONSTRAINT fk_frb_guest     FOREIGN KEY (guest_key)        REFERENCES DIM_GUEST       (guest_key),
    CONSTRAINT fk_frb_country   FOREIGN KEY (country_key)      REFERENCES DIM_COUNTRY     (country_key),
    CONSTRAINT fk_frb_star      FOREIGN KEY (star_rating_key)  REFERENCES DIM_STAR_RATING (star_rating_key),
    CONSTRAINT fk_frb_checkin   FOREIGN KEY (checkin_date_key)  REFERENCES DIM_DATE       (date_key),
    CONSTRAINT fk_frb_checkout  FOREIGN KEY (checkout_date_key) REFERENCES DIM_DATE       (date_key)
);
