
CREATE TABLE Artysci (
    Id_Artysta SERIAL PRIMARY KEY,
    Imie VARCHAR(25) NOT NULL,
    Nazwisko VARCHAR(25) NOT NULL,
    Rok_Urodzenia INT NOT NULL CHECK (Rok_Urodzenia <= EXTRACT(YEAR FROM CURRENT_DATE)),
    Rok_Smierci INT CHECK (Rok_Smierci IS NULL OR (Rok_Smierci <= EXTRACT(YEAR FROM CURRENT_DATE) AND Rok_Smierci >= Rok_Urodzenia))
);

CREATE TABLE Eksponaty (
    Id_Eksponat SERIAL PRIMARY KEY,
    Tytul VARCHAR(25) NOT NULL,
    Id_Artysty INT REFERENCES Artysci(Id_Artysta) ON DELETE CASCADE,
    Typ VARCHAR(25) NOT NULL,
    Wysokosc DECIMAL(8,2) NOT NULL CHECK (Wysokosc > 0),
    Szerokosc DECIMAL(8,2) NOT NULL CHECK (Szerokosc > 0),
    Waga DECIMAL(8,2) NOT NULL CHECK (Waga > 0),
    Stan CHAR(3) NOT NULL CHECK (Stan IN ('wyp', 'wys', 'mag')), --'wyp' = wypozyczony, 'wys' = wystawa, 'mag' = magazyn
    Cenny BOOLEAN NOT NULL DEFAULT FALSE
);

CREATE TABLE Galerie (
    Id_Galeria SERIAL PRIMARY KEY,
    Nazwa_Gal VARCHAR(20) NOT NULL UNIQUE,
    Lokalizacja_Gal VARCHAR(25) NOT NULL
);

CREATE TABLE Wystawy (
    Id_Wys SERIAL PRIMARY KEY,
    Id_Eksp INT REFERENCES Eksponaty(Id_Eksponat) ON DELETE CASCADE,
    Id_Gal INT REFERENCES Galerie(Id_Galeria) ON DELETE CASCADE,
    Nr_Sala INT NOT NULL UNIQUE CHECK (Nr_Sala > 0),
    Poczatek DATE NOT NULL,
    Koniec DATE NOT NULL CHECK (Koniec >= Poczatek)
);

CREATE TABLE Instytucje (
    Id_Instytucja SERIAL PRIMARY KEY,
    Nazwa_Inst VARCHAR(25) NOT NULL UNIQUE,
    Miasto VARCHAR(25) NOT NULL
);

CREATE TABLE Wypozyczenia (
    Id_Wyp SERIAL PRIMARY KEY,
    Id_Eks INT REFERENCES Eksponaty(Id_Eksponat) ON DELETE CASCADE,
    Id_Inst INT REFERENCES Instytucje(Id_Instytucja) ON DELETE CASCADE,
    Data_Wyp DATE NOT NULL,
    Data_Zwrot DATE CHECK (Data_Zwrot >= Data_Wyp)
);

CREATE TABLE Zamkniecia (
    Id_Zamkniecie SERIAL PRIMARY KEY,
    Id_Eksponat INT REFERENCES Eksponaty(Id_Eksponat) ON DELETE CASCADE,
    Data_Pocz DATE NOT NULL,
    Data_Kon DATE NOT NULL CHECK (Data_Kon >= Data_Pocz)
);

-- Funkcja sprawdzająca, czy eksponat jest cenny i blokująca jego wypożyczenie
CREATE OR REPLACE FUNCTION sprawdz_czy_cenny() RETURNS TRIGGER AS $$
DECLARE
    czy_jest_cenny BOOLEAN;
BEGIN
    -- Pobranie wartości kolumny Cenny dla wypożyczanego eksponatu
    SELECT Cenny INTO czy_jest_cenny FROM Eksponaty WHERE Id_Eksponat = NEW.Id_Eks;
    
    -- Jeśli eksponat jest cenny, blokujemy operację
    IF czy_jest_cenny THEN
        RAISE EXCEPTION 'Eksponat % jest cenny i nie może być wypożyczony.', NEW.Id_Eks;
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Wyzwalacz dla funkcji sprawdzającej, czy eksponat jest cenny
CREATE TRIGGER sprawdz_czy_cenny_trg
BEFORE INSERT OR UPDATE ON Wypozyczenia
FOR EACH ROW
EXECUTE FUNCTION sprawdz_czy_cenny();


-- Funkcja sprawdzająca, czy eksponat nie był wypożyczony dłużej niż 30 dni w roku
CREATE OR REPLACE FUNCTION sprawdz_limit_wypozyczen() RETURNS TRIGGER AS $$
DECLARE
    laczny_czas_wypozyczen INT;
BEGIN
    -- Obliczenie łącznego czasu wypożyczeń dla danego eksponatu w bieżącym roku
    SELECT COALESCE(SUM(Data_Zwrot - Data_Wyp), 0)
    INTO laczny_czas_wypozyczen
    FROM Wypozyczenia
    WHERE Id_Eks = NEW.Id_Eks AND EXTRACT(YEAR FROM Data_Wyp) = EXTRACT(YEAR FROM CURRENT_DATE);
    
    -- Sprawdzenie, czy nowe wypożyczenie nie przekroczy limitu 30 dni
    IF (laczny_czas_wypozyczen + (NEW.Data_Zwrot - NEW.Data_Wyp)) > 30 THEN
        RAISE EXCEPTION 'Eksponat % był już wypożyczony przez % dni w tym roku i nie może być wypożyczony dłużej niż 30 dni.', NEW.Id_Eks, laczny_czas_wypozyczen;
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Wyzwalacz dla funkcji sprawdzającej limit 30 dni wypożyczeń
CREATE TRIGGER sprawdz_limit_wypozyczen_trg
BEFORE INSERT OR UPDATE ON Wypozyczenia
FOR EACH ROW
EXECUTE FUNCTION sprawdz_limit_wypozyczen();


-- Funkcja sprawdzająca, czy muzeum ma przynajmniej jeden eksponat każdego artysty
CREATE OR REPLACE FUNCTION eksp_art() RETURNS TRIGGER AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM Eksponaty
        WHERE Id_Artysty = OLD.Id_Artysty
          AND Stan IN ('wys', 'mag')
    ) THEN
        RAISE EXCEPTION 'Artysta % nie ma zadnego eksponatu ani w galerii, ani w magazynie', OLD.Id_Artysty;
    END IF;

    RETURN OLD;
END;
$$ LANGUAGE plpgsql;

-- Wyzwalacz dla funkcji sprawdzającej, czy jest co najmniej jeden eksponat kazdego artysty 
CREATE TRIGGER eksp_art_trig
AFTER DELETE ON Eksponaty
FOR EACH ROW
EXECUTE FUNCTION eksp_art();


