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

USE hotel_reservations;

-- ─────────────────────────────────────────────────────────────────────────────
-- LOOKUP / REFERENCE TABLES
-- ─────────────────────────────────────────────────────────────────────────────

CREATE TABLE hotel_chain (
    hotel_chain_id  INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    code            VARCHAR(10)     NOT NULL,
    name            VARCHAR(100)    NOT NULL,
    PRIMARY KEY (hotel_chain_id),
    UNIQUE KEY uq_chain_code (code)
);

CREATE TABLE country (
    country_id  INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    code        CHAR(2)         NOT NULL,
    name        VARCHAR(100)    NOT NULL,
    currency    VARCHAR(10)     NOT NULL,
    PRIMARY KEY (country_id),
    UNIQUE KEY uq_country_code (code)
);

CREATE TABLE star_rating (
    star_rating_id  INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    code            TINYINT UNSIGNED NOT NULL,
    description     VARCHAR(20)     NOT NULL,
    PRIMARY KEY (star_rating_id),
    UNIQUE KEY uq_star_code (code)
);

CREATE TABLE hotel_characteristic (
    characteristic_id   INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    code                VARCHAR(20)     NOT NULL,
    description         VARCHAR(100)    NOT NULL,
    PRIMARY KEY (characteristic_id),
    UNIQUE KEY uq_char_code (code)
);

CREATE TABLE room_type (
    room_type_id    INT UNSIGNED        NOT NULL AUTO_INCREMENT,
    code            VARCHAR(20)         NOT NULL,
    description     VARCHAR(100)        NOT NULL,
    standard_rate   DECIMAL(10,2)       NOT NULL,
    smoking_yn      BOOLEAN             NOT NULL DEFAULT FALSE,
    PRIMARY KEY (room_type_id),
    UNIQUE KEY uq_room_type_code (code)
);

CREATE TABLE rate_period (
    rate_period_id  INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    code            VARCHAR(20)     NOT NULL,
    description     VARCHAR(50)     NOT NULL,
    month_from      TINYINT UNSIGNED NOT NULL,
    month_to        TINYINT UNSIGNED NOT NULL,
    PRIMARY KEY (rate_period_id),
    UNIQUE KEY uq_rate_period_code (code)
);

-- ─────────────────────────────────────────────────────────────────────────────
-- CORE ENTITIES
-- ─────────────────────────────────────────────────────────────────────────────

CREATE TABLE hotel (
    hotel_id        INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    hotel_chain_id  INT UNSIGNED,
    country_id      INT UNSIGNED    NOT NULL,
    star_rating_id  INT UNSIGNED    NOT NULL,
    code            VARCHAR(20)     NOT NULL,
    name            VARCHAR(150)    NOT NULL,
    address         VARCHAR(200),
    postcode        VARCHAR(20),
    city            VARCHAR(100)    NOT NULL,
    url             VARCHAR(200),
    PRIMARY KEY (hotel_id),
    UNIQUE KEY uq_hotel_code (code),
    CONSTRAINT fk_hotel_chain   FOREIGN KEY (hotel_chain_id) REFERENCES hotel_chain   (hotel_chain_id),
    CONSTRAINT fk_hotel_country FOREIGN KEY (country_id)    REFERENCES country        (country_id),
    CONSTRAINT fk_hotel_star    FOREIGN KEY (star_rating_id) REFERENCES star_rating   (star_rating_id)
);

CREATE TABLE hotel_room (
    room_id         INT UNSIGNED        NOT NULL AUTO_INCREMENT,
    hotel_id        INT UNSIGNED        NOT NULL,
    room_type_id    INT UNSIGNED        NOT NULL,
    room_number     VARCHAR(10)         NOT NULL,
    floor           TINYINT UNSIGNED    NOT NULL DEFAULT 0,
    PRIMARY KEY (room_id),
    UNIQUE KEY uq_hotel_room (hotel_id, room_number),
    CONSTRAINT fk_room_hotel    FOREIGN KEY (hotel_id)     REFERENCES hotel      (hotel_id),
    CONSTRAINT fk_room_type     FOREIGN KEY (room_type_id) REFERENCES room_type  (room_type_id)
);

CREATE TABLE guest (
    guest_id    INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    country_id  INT UNSIGNED,
    name        VARCHAR(150)    NOT NULL,
    email       VARCHAR(150),
    address     VARCHAR(200),
    city        VARCHAR(100),
    PRIMARY KEY (guest_id),
    CONSTRAINT fk_guest_country FOREIGN KEY (country_id) REFERENCES country (country_id)
);

CREATE TABLE booking (
    booking_id  INT UNSIGNED    NOT NULL AUTO_INCREMENT,
    guest_id    INT UNSIGNED    NOT NULL,
    hotel_id    INT UNSIGNED    NOT NULL,
    date_from   DATE            NOT NULL,
    date_to     DATE            NOT NULL,
    status      ENUM('confirmed', 'cancelled', 'completed', 'no_show') NOT NULL DEFAULT 'confirmed',
    created_at  DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (booking_id),
    CONSTRAINT fk_booking_guest FOREIGN KEY (guest_id) REFERENCES guest (guest_id),
    CONSTRAINT fk_booking_hotel FOREIGN KEY (hotel_id) REFERENCES hotel (hotel_id)
);

CREATE TABLE room_booking (
    room_booking_id INT UNSIGNED        NOT NULL AUTO_INCREMENT,
    booking_id      INT UNSIGNED        NOT NULL,
    room_id         INT UNSIGNED        NOT NULL,
    date_from       DATE                NOT NULL,
    date_to         DATE                NOT NULL,
    nightly_rate    DECIMAL(10,2)       NOT NULL,
    total_amount    DECIMAL(10,2)       NOT NULL,
    PRIMARY KEY (room_booking_id),
    CONSTRAINT fk_rb_booking    FOREIGN KEY (booking_id) REFERENCES booking    (booking_id),
    CONSTRAINT fk_rb_room       FOREIGN KEY (room_id)    REFERENCES hotel_room  (room_id)
);

-- ─────────────────────────────────────────────────────────────────────────────
-- JUNCTION TABLES
-- ─────────────────────────────────────────────────────────────────────────────

CREATE TABLE hotel_hotel_characteristic (
    hotel_id            INT UNSIGNED NOT NULL,
    characteristic_id   INT UNSIGNED NOT NULL,
    PRIMARY KEY (hotel_id, characteristic_id),
    CONSTRAINT fk_hhc_hotel FOREIGN KEY (hotel_id)          REFERENCES hotel               (hotel_id),
    CONSTRAINT fk_hhc_char  FOREIGN KEY (characteristic_id) REFERENCES hotel_characteristic (characteristic_id)
);

CREATE TABLE period_room_rate (
    room_type_id    INT UNSIGNED    NOT NULL,
    rate_period_id  INT UNSIGNED    NOT NULL,
    rate            DECIMAL(10,2)   NOT NULL,
    PRIMARY KEY (room_type_id, rate_period_id),
    CONSTRAINT fk_prr_type   FOREIGN KEY (room_type_id)   REFERENCES room_type   (room_type_id),
    CONSTRAINT fk_prr_period FOREIGN KEY (rate_period_id) REFERENCES rate_period (rate_period_id)
);
