-- Таблицы базы данных Ресторан

CREATE TABLE IF NOT EXISTS "Персонал" (
    id_персонала SERIAL PRIMARY KEY,
    фио VARCHAR(100) NOT NULL,
    год_рождения INT,
    должность VARCHAR(50),
    оклад NUMERIC(10,2) CHECK (оклад >= 0),
    телефон VARCHAR(20),
    адрес VARCHAR(200),
    паспортные_данные VARCHAR(50)
);

CREATE TABLE IF NOT EXISTS "Блюда" (
    id_блюда SERIAL PRIMARY KEY,
    блюдо VARCHAR(100) NOT NULL,
    категория VARCHAR(50),
    вес_г INT
);

CREATE TABLE IF NOT EXISTS "Склад" (
    id_ингредиента SERIAL PRIMARY KEY,
    ингредиент VARCHAR(100) NOT NULL,
    вес_кг NUMERIC(8,3) CHECK (вес_кг >= 0),
    цена_руб NUMERIC(10,2) CHECK (цена_руб >= 0)
);

CREATE TABLE IF NOT EXISTS "Заказы" (
    id_заказа SERIAL PRIMARY KEY,
    код_заказа VARCHAR(20) UNIQUE NOT NULL,
    дата_заказа DATE NOT NULL,
    id_персонала INT REFERENCES "Персонал"(id_персонала)
);

CREATE TABLE IF NOT EXISTS audit_log (
    id SERIAL PRIMARY KEY,
    таблица VARCHAR(50),
    операция VARCHAR(10),
    старые_данные TEXT,
    новые_данные TEXT,
    пользователь VARCHAR(50) DEFAULT current_user,
    время TIMESTAMP DEFAULT now()
);

-- Триггер логирования Персонал
CREATE OR REPLACE FUNCTION log_персонал() RETURNS trigger AS $$
BEGIN
    IF TG_OP = 'DELETE' THEN
        INSERT INTO audit_log(таблица,операция,старые_данные)
        VALUES ('Персонал','DELETE',ROW(OLD.*)::text);
        RETURN OLD;
    ELSIF TG_OP = 'UPDATE' THEN
        INSERT INTO audit_log(таблица,операция,старые_данные,новые_данные)
        VALUES ('Персонал','UPDATE',ROW(OLD.*)::text,ROW(NEW.*)::text);
        RETURN NEW;
    ELSIF TG_OP = 'INSERT' THEN
        INSERT INTO audit_log(таблица,операция,новые_данные)
        VALUES ('Персонал','INSERT',ROW(NEW.*)::text);
        RETURN NEW;
    END IF;
END; $$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_audit_персонал ON "Персонал";
CREATE TRIGGER trg_audit_персонал
AFTER INSERT OR UPDATE OR DELETE ON "Персонал"
FOR EACH ROW EXECUTE FUNCTION log_персонал();

-- Триггер логирования Заказы
CREATE OR REPLACE FUNCTION log_заказы() RETURNS trigger AS $$
BEGIN
    IF TG_OP = 'DELETE' THEN
        INSERT INTO audit_log(таблица,операция,старые_данные)
        VALUES ('Заказы','DELETE',ROW(OLD.*)::text);
        RETURN OLD;
    ELSIF TG_OP = 'UPDATE' THEN
        INSERT INTO audit_log(таблица,операция,старые_данные,новые_данные)
        VALUES ('Заказы','UPDATE',ROW(OLD.*)::text,ROW(NEW.*)::text);
        RETURN NEW;
    ELSIF TG_OP = 'INSERT' THEN
        INSERT INTO audit_log(таблица,операция,новые_данные)
        VALUES ('Заказы','INSERT',ROW(NEW.*)::text);
        RETURN NEW;
    END IF;
END; $$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_audit_заказы ON "Заказы";
CREATE TRIGGER trg_audit_заказы
AFTER INSERT OR UPDATE OR DELETE ON "Заказы"
FOR EACH ROW EXECUTE FUNCTION log_заказы();

-- Роли
DO $$ BEGIN
  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'db_admin') THEN
    CREATE ROLE db_admin LOGIN PASSWORD 'Admin@123';
  END IF;
END $$;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO db_admin;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO db_admin;

DO $$ BEGIN
  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'db_manager') THEN
    CREATE ROLE db_manager LOGIN PASSWORD 'Manager@123';
  END IF;
END $$;
GRANT SELECT, INSERT, UPDATE ON "Персонал","Заказы","Блюда","Склад" TO db_manager;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO db_manager;

DO $$ BEGIN
  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'db_waiter') THEN
    CREATE ROLE db_waiter LOGIN PASSWORD 'Waiter@123';
  END IF;
END $$;
GRANT SELECT ON "Блюда","Склад","Персонал" TO db_waiter;
GRANT SELECT, INSERT ON "Заказы" TO db_waiter;

DO $$ BEGIN
  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'db_readonly') THEN
    CREATE ROLE db_readonly LOGIN PASSWORD 'Readonly@123';
  END IF;
END $$;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO db_readonly;
