DROP TABLE Artysta cascade;
DROP TABLE Eksponat cascade;
DROP TABLE Magazyn cascade;
DROP TABLE Ekspozycje cascade;
DROP TABLE Wypozyczenia cascade;
DROP TABLE Galeria cascade;
DROP TABLE Instytucje cascade;

--Deklaracje tabel--

CREATE TABLE Artysta (
    id SERIAL PRIMARY KEY,
    imie VARCHAR(50) NOT NULL,
    nazwisko VARCHAR(50) NOT NULL,
    rok_urodzenia DATE NOT NULL,
    rok_smierci DATE
);

CREATE TABLE Eksponat (
    id SERIAL PRIMARY KEY,
    artysta_id INTEGER REFERENCES Artysta ON DELETE SET NULL,
    tytul VARCHAR(50) NOT NULL,
    typ VARCHAR(50) NOT NULL,
    wysokosc INTEGER NOT NULL CHECK (wysokosc>0),
    szerokosc INTEGER NOT NULL CHECK (szerokosc>0),
    waga INTEGER NOT NULL CHECK (waga>0),
    cenny BOOLEAN DEFAULT FALSE
);

CREATE TABLE Magazyn (
    id_magazynowania SERIAL PRIMARY KEY,
    eksponat_id INTEGER NOT NULL REFERENCES Eksponat ON DELETE cascade,
    data_wejscia DATE NOT NULL,
    data_wyjscia DATE 
);

CREATE TABLE Instytucje (
    id SERIAL PRIMARY KEY,
    nazwa VARCHAR(50) NOT NULL,
    miasto VARCHAR(50) NOT NULL
);

CREATE TABLE Galeria (
    id SERIAL PRIMARY KEY,
    lokalizacja VARCHAR(100) NOT NULL,
    nazwa VARCHAR(50) NOT NULL
);

CREATE TABLE Ekspozycje (
    id_ekspozycji SERIAL PRIMARY KEY,
    galeria_id INTEGER REFERENCES Galeria,
    eksponat_id INTEGER REFERENCES Eksponat ON DELETE CASCADE,
    sala INTEGER NOT NULL CHECK(sala>0),
    data_rozpoczecia DATE NOT NULL,
    data_zakonczenia DATE
);

CREATE TABLE Wypozyczenia (
    id_wypozyczenia SERIAL PRIMARY KEY,
    eksponat_id INTEGER REFERENCES Eksponat ON DELETE CASCADE,
    id_instytucji INTEGER REFERENCES Instytucje,
    data_rozpoczecia DATE NOT NULL,
    data_zakonczenia DATE
);

--Funkcje--

CREATE OR REPLACE FUNCTION czy_cenny(eksponat_id INTEGER) 
RETURNS BOOLEAN
LANGUAGE plpgsql
AS $$
DECLARE is_cenny BOOLEAN;
BEGIN 
 SELECT cenny INTO is_cenny FROM Eksponat WHERE id = eksponat_id;

 RETURN is_cenny;
END;
$$;

CREATE OR REPLACE FUNCTION czy_30_dni(
    eksponat_id_param INTEGER
)
RETURNS BOOLEAN
LANGUAGE plpgsql
AS $$
DECLARE
    ile_poza INTEGER := 0;
BEGIN
    SELECT COALESCE(SUM(COALESCE(data_zakonczenia, CURRENT_DATE) - data_rozpoczecia), 0)
    INTO ile_poza
    FROM Wypozyczenia
    WHERE eksponat_id = eksponat_id_param
      AND EXTRACT(YEAR FROM data_rozpoczecia) = EXTRACT(YEAR FROM CURRENT_DATE);

    IF ile_poza >= 30 THEN
        RETURN FALSE;
    ELSE
        RETURN TRUE;
    END IF;
END;
$$;

CREATE OR REPLACE FUNCTION czy_zostanie(
    eksponat_id_param INTEGER
)
RETURNS BOOLEAN
LANGUAGE plpgsql
AS $$
DECLARE
    A_artysta_id INTEGER;
    pozostale INTEGER;
BEGIN
    SELECT artysta_id INTO A_artysta_id 
    FROM Eksponat 
    WHERE id = eksponat_id_param;

    IF A_artysta_id IS NULL THEN
        RETURN TRUE;
    END IF;

    SELECT COUNT(*) INTO pozostale 
    FROM Eksponat e
    LEFT JOIN Magazyn m 
        ON m.eksponat_id = e.id AND m.data_wyjscia IS NULL
    LEFT JOIN Ekspozycje ex 
        ON ex.eksponat_id = e.id AND ex.data_zakonczenia IS NULL
    WHERE e.artysta_id = A_artysta_id 
      AND (m.eksponat_id IS NOT NULL OR ex.eksponat_id IS NOT NULL);

    IF pozostale = 1 THEN
        RETURN FALSE;
    ELSE
        RETURN TRUE;
    END IF;
END;
$$;

--Funkcje składowane--

CREATE OR REPLACE PROCEDURE z_ekspozycji_do_magazynu(A_eksponat_id INTEGER)
LANGUAGE plpgsql
AS $$
BEGIN 

--Sprawdzenie czy eksponat na ekspozycji.
 IF NOT EXISTS (SELECT 1 FROM Ekspozycje WHERE eksponat_id = A_eksponat_id
 AND data_zakonczenia IS NULL) THEN
  RAISE EXCEPTION 'Błąd! Eksponat nie znajduje się na ekspozycji.';
 END IF;

 UPDATE Ekspozycje 
 SET data_zakonczenia = CURRENT_DATE
 WHERE eksponat_id = A_eksponat_id AND data_zakonczenia IS NULL;

 INSERT INTO Magazyn (eksponat_id, data_wejscia) VALUES (A_eksponat_id, CURRENT_DATE);

 RAISE NOTICE 'Eksponat zostal przeniesiony do magazynu.';
END;
$$;

CREATE OR REPLACE PROCEDURE z_magazynu_do_ekspozycji (A_eksponat_id INTEGER, A_galeria_id INTEGER, A_sala INTEGER)
LANGUAGE plpgsql
AS $$
BEGIN 

--Sprawdzenie czy eksponat w magazynie
 IF NOT EXISTS (SELECT 1 FROM Magazyn WHERE eksponat_id = A_eksponat_id
 AND data_wyjscia IS NULL) THEN
  RAISE EXCEPTION 'Błąd! Eksponat nie znajduje się w magazynie.';
 END IF;

 UPDATE Magazyn 
 SET data_wyjscia = CURRENT_DATE
 WHERE eksponat_id = A_eksponat_id AND data_wyjscia IS NULL;

 INSERT INTO Ekspozycje (galeria_id, eksponat_id, sala, data_rozpoczecia) VALUES (A_galeria_id, A_eksponat_id, 
 A_sala, CURRENT_DATE);

 RAISE NOTICE 'Eksponat zostal przeniesiony na ekspozycje.';
END;
$$;

CREATE OR REPLACE PROCEDURE wypozycz_z_magazynu (A_eksponat_id INTEGER, A_id_instytucji INTEGER)
LANGUAGE plpgsql
AS $$
BEGIN 

--Sprawdzenie czy eksponat w magazynie.
 IF NOT EXISTS (SELECT 1 FROM Magazyn WHERE eksponat_id = A_eksponat_id
 AND data_wyjscia IS NULL) THEN
  RAISE EXCEPTION 'Błąd! Eksponat nie znajduje się w magazynie.';
 END IF;

--Czy eksponat cenny.
 IF czy_cenny(A_eksponat_id) THEN
  RAISE EXCEPTION 'Eksponat jest zbyt cenny i nie może zostać wypożyczony.';
 END IF;

 UPDATE Magazyn 
 SET data_wyjscia = CURRENT_DATE
 WHERE eksponat_id = A_eksponat_id AND data_wyjscia IS NULL;

 INSERT INTO Wypozyczenia (eksponat_id, id_instytucji, data_rozpoczecia) VALUES (A_eksponat_id, 
 A_id_instytucji, CURRENT_DATE);

 RAISE NOTICE 'Eksponat zostal wypozyczony.';
END;
$$;

CREATE OR REPLACE PROCEDURE wypozycz_z_ekspozycji(A_eksponat_id INTEGER, A_id_instytucji INTEGER)
LANGUAGE plpgsql
AS $$
BEGIN 

--Sprawdzenie czy eksponat na ekspozycji.
 IF NOT EXISTS (SELECT 1 FROM Ekspozycje WHERE eksponat_id = A_eksponat_id
 AND data_zakonczenia IS NULL) THEN
  RAISE EXCEPTION 'Błąd! Eksponat nie znajduje się na ekspozycji.';
 END IF;

--Czy eksponat cenny.
  IF czy_cenny(A_eksponat_id) THEN
  RAISE EXCEPTION 'Eksponat jest zbyt cenny i nie może zostać wypożyczony.';
 END IF;

 UPDATE Ekspozycje 
 SET data_zakonczenia = CURRENT_DATE
 WHERE eksponat_id = A_eksponat_id AND data_zakonczenia IS NULL;

 INSERT INTO Wypozyczenia (eksponat_id, id_instytucji, data_rozpoczecia) VALUES (A_eksponat_id, 
 A_id_instytucji, CURRENT_DATE);

 RAISE NOTICE 'Eksponat zostal wypozyczony.';
END;
$$;

CREATE OR REPLACE PROCEDURE zakoncz_wypozyczenie (A_eksponat_id INTEGER)
LANGUAGE plpgsql
AS $$
BEGIN 

--Sprawdzenie czy eksponat na wypożyczeniu.
 IF NOT EXISTS (SELECT 1 FROM Wypozyczenia WHERE eksponat_id = A_eksponat_id
 AND data_zakonczenia IS NULL) THEN
  RAISE EXCEPTION 'Błąd! Eksponat nie znajduje się na wypożyczeniu.';
 END IF;

 UPDATE Wypozyczenia 
 SET data_zakonczenia = CURRENT_DATE
 WHERE eksponat_id = A_eksponat_id AND data_zakonczenia IS NULL;

 INSERT INTO Magazyn (eksponat_id, data_wejscia) VALUES (A_eksponat_id, CURRENT_DATE);

 RAISE NOTICE 'Wypozyczenie eksponatu zostało zakończone.';
END;
$$;

