--CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS hstore;

CREATE DATABASE pager_data;
CREATE USER admin WITH ENCRYPTED PASSWORD '1234';
GRANT ALL PRIVILEGES ON DATABASE pager_data TO admin;

-- === Devices ===
CREATE TABLE Devices (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    euid VARCHAR(16) NOT NULL UNIQUE, -- LoRaWAN Extended Unique ID (hex, 8 bytes)
    name VARCHAR(64) NOT NULL, -- ! Not Unique

    fw_version VARCHAR(24) NOT NULL,

    charge NUMERIC(5,2) CHECK (charge >= 0 AND charge <= 100), -- battery in %
    last_online TIMESTAMPTZ, -- ! NULL

    -- Location fields:
    latitude    DOUBLE PRECISION CHECK (latitude >= -90 AND latitude <= 90),
    longitude   DOUBLE PRECISION CHECK (longitude >= -180 AND longitude <= 180),
    altitude    DOUBLE PRECISION
);

CREATE TABLE Messages (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    sender_id INT NOT NULL REFERENCES Devices(id) ON DELETE SET NULL,
    receiver_id INT REFERENCES Devices(id) ON DELETE SET NULL, -- ! NULL
    payload VARCHAR(256)
);

CREATE TABLE Statuses (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    device_id INT NOT NULL REFERENCES Devices(id) ON DELETE CASCADE,
    payload VARCHAR(256)
);

-- === Roles ===
CREATE TABLE Roles (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    name VARCHAR(64) NOT NULL UNIQUE,
    description VARCHAR(128) NOT NULL DEFAULT 'Role description'
);

INSERT INTO Roles (name, description) VALUES ('Admin', 'Should do everything.'); -- Admin role

CREATE TABLE Permissions (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    name VARCHAR(64) NOT NULL UNIQUE,
    description VARCHAR(128) NOT NULL DEFAULT 'Permission description'
);

INSERT INTO Permissions (name, description) VALUES ('Everything', 'Can do everything.'); -- Admin permission

-- Join table for Roles & Permissions
CREATE TABLE RolesPermissions (
    role_id INT NOT NULL REFERENCES Roles(id),
    permission_id INT NOT NULL REFERENCES Permissions(id)
);

INSERT INTO RolesPermissions (role_id, permission_id) VALUES (1, 1); -- Tie together role & permission

-- === Users ===
CREATE TABLE Users (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    name VARCHAR(64) UNIQUE NOT NULL,
    password VARCHAR(64) NOT NULL,
    role_id INT DEFAULT 2 REFERENCES Roles(id) ON DELETE SET DEFAULT, -- default low privilleges
    last_online TIMESTAMPTZ -- ! NULL
);

INSERT INTO Users (name, password, role_id) VALUES ('Admin', 'admin', 1); -- Admin user

CREATE TABLE NFC_Cards (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    user_id INT REFERENCES Users(id) ON DELETE SET NULL, -- ! NULL
    device_id INT REFERENCES Devices(id) ON DELETE SET NULL, -- ! NULL
    uid VARCHAR(7) NOT NULL UNIQUE,
    CONSTRAINT uid_length CHECK (length(uid) = 4 OR length(uid) = 7) -- Check for valid UUID
);

-- === Logs ===
CREATE TABLE Logs (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    db_user TEXT DEFAULT current_user
);

CREATE TABLE LogsUsers (
    log_id INT REFERENCES Logs(id) ON DELETE CASCADE,
    user_id INT REFERENCES Users(id) ON DELETE CASCADE
);

CREATE TABLE LogsDevices (
    log_id INT REFERENCES Logs(id) ON DELETE CASCADE,
    device_id INT REFERENCES Devices(id) ON DELETE CASCADE
);

CREATE TABLE Changes (
    id SERIAL PRIMARY KEY,
    log_id INT NOT NULL REFERENCES Logs(id) ON DELETE CASCADE,
    table_name TEXT NOT NULL,
    operation TEXT NOT NULL,
    old_value hstore, -- ! NULL
    new_value hstore, -- ! NULL
    CONSTRAINT change_diff CHECK (old_value != new_value)
);
