
CREATE TABLE Galeria (
    id_galerii VARCHAR(3)  PRIMARY KEY,
    nazwa      VARCHAR(50) NOT NULL,
    miasto     VARCHAR(50) NOT NULL
);

CREATE TABLE Artysta (
    id_artysty    VARCHAR(3)  PRIMARY KEY,
    imie          VARCHAR(50) NOT NULL,
    nazwisko      VARCHAR(50) NOT NULL,
    rok_urodzenia INT         NOT NULL,
    rok_smierci   INT,
    CONSTRAINT chk_artysta_dates CHECK (rok_smierci IS NULL OR rok_urodzenia < rok_smierci)
);

CREATE TABLE Eksponaty (
    id_eksponatu VARCHAR(3)    PRIMARY KEY,
    tytul        VARCHAR(50)   NOT NULL,
    typ          VARCHAR(50)   NOT NULL,
    wysokosc     DECIMAL(10,2) NOT NULL,
    szerokosc    DECIMAL(10,2) NOT NULL,
    waga         DECIMAL(10,2) NOT NULL,
    id_artysty   VARCHAR(3)    REFERENCES Artysta (id_artysty),
    czy_cenny    BOOLEAN       NOT NULL
);

CREATE TABLE Instytucje (
    id_instytucji VARCHAR(3)  PRIMARY KEY,
    nazwa         VARCHAR(50) NOT NULL,
    miasto        VARCHAR(50) NOT NULL
);

CREATE TABLE Historia (
    id_historii      SERIAL      PRIMARY KEY,
    id_galerii       VARCHAR(3)  REFERENCES Galeria(id_galerii),
    id_eksponatu     VARCHAR(3)  NOT NULL REFERENCES Eksponaty(id_eksponatu),
    status           VARCHAR(15) NOT NULL CHECK (status IN ('magazyn', 'galeria', 'wypozyczony')),
    data_rozpoczecia DATE        NOT NULL,
    data_zakonczenia DATE,
    id_instytucji    VARCHAR(3)  REFERENCES Instytucje(id_instytucji),
    id_sali          VARCHAR(3),
    CONSTRAINT chk_data_wypozyczenia CHECK (data_zakonczenia IS NULL OR data_rozpoczecia < data_zakonczenia)
);


-----------------------


CREATE OR REPLACE FUNCTION zamknij_poprzedni_pobyt()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE Historia SET data_zakonczenia = NEW.data_rozpoczecia 
    WHERE id_eksponatu = NEW.id_eksponatu AND data_zakonczenia IS NULL AND id_historii <> NEW.id_historii;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;



CREATE TRIGGER tg_zamknij_poprzedni_pobyt
BEFORE INSERT OR UPDATE ON Historia
FOR EACH ROW
EXECUTE PROCEDURE zamknij_poprzedni_pobyt();

-----------------------


CREATE OR REPLACE FUNCTION minimum_jeden_w_muzeum()
RETURNS TRIGGER AS $$
DECLARE
    liczba_eksp_w_muzeum INT;
    artysta_id VARCHAR(3);
BEGIN
    IF (NEW.status = 'wypozyczony') THEN
        SELECT e.id_artysty INTO artysta_id FROM Eksponaty e WHERE e.id_eksponatu = NEW.id_eksponatu;

        SELECT COUNT(*) INTO liczba_eksp_w_muzeum FROM Historia h JOIN Eksponaty e ON e.id_eksponatu = h.id_eksponatu
        WHERE e.id_artysty = artysta_id AND h.status IN ('magazyn', 'galeria') AND (h.data_zakonczenia IS NULL 
        OR h.data_zakonczenia >= CURRENT_DATE) AND h.id_historii <> NEW.id_historii;

        IF liczba_eksp_w_muzeum = 0 THEN
            RAISE EXCEPTION 'Nie mozna wypozyczyc eksponatu - artysta % nie bedzie mial zadnego dziela w muzeum', artysta_id;
        END IF;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tg_minimum_jeden_w_muzeum
BEFORE INSERT OR UPDATE ON Historia
FOR EACH ROW
EXECUTE PROCEDURE minimum_jeden_w_muzeum();


-----------------------------


CREATE OR REPLACE FUNCTION sprawdz_czas_wypozyczenia()
RETURNS TRIGGER AS $$
DECLARE
    czas_wypozyczenia INT;
    biezacy_rok INT := EXTRACT(YEAR FROM CURRENT_DATE);
BEGIN
    IF (NEW.status = 'wypozyczony') THEN
        SELECT COALESCE(SUM(GREATEST(0,(LEAST(COALESCE(data_zakonczenia, CURRENT_DATE), make_date(biezacy_rok, 12, 31))- 
	GREATEST(data_rozpoczecia, make_date(biezacy_rok, 1, 1)) + 1))), 0) INTO czas_wypozyczenia	
    	FROM Historia WHERE id_eksponatu = NEW.id_eksponatu AND status = 'wypozyczony'
        AND data_rozpoczecia <= make_date(biezacy_rok, 12, 31)
        AND (data_zakonczenia IS NULL OR data_zakonczenia >= make_date(biezacy_rok, 1, 1));

    	IF czas_wypozyczenia > 30 THEN
    	    RAISE EXCEPTION 'Nie mozna wypozyczyc eksponatu, ktory byl w tym roku poza muzeum ponad 30 dni';
    	END IF;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tg_sprawdz_czas_wypozyczenia
BEFORE INSERT OR UPDATE ON Historia
FOR EACH ROW
EXECUTE PROCEDURE sprawdz_czas_wypozyczenia();


------------------------


CREATE OR REPLACE FUNCTION czy_eksponat_juz_wypozyczony()
RETURNS TRIGGER AS $$
DECLARE
    nie_zwr INT;
BEGIN
    IF NEW.status = 'wypozyczony' THEN
        SELECT COUNT(*) INTO nie_zwr FROM Historia WHERE id_eksponatu = NEW.id_eksponatu
        AND status = 'wypozyczony' AND data_zakonczenia IS NULL;

        IF nie_zwr > 0 THEN
            RAISE EXCEPTION 'Eksponat jest już wypożyczony i nie można go wypożyczyć ponownie!';
        END IF;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;


CREATE TRIGGER tg_czy_eksponat_juz_wypozyczony
BEFORE INSERT OR UPDATE ON Historia
FOR EACH ROW
EXECUTE PROCEDURE czy_eksponat_juz_wypozyczony();


------------------------


CREATE OR REPLACE FUNCTION zakaz_nakladania_statusu()
RETURNS TRIGGER AS $$
DECLARE
    licznik INT;
BEGIN
    SELECT COUNT(*) INTO licznik FROM Historia WHERE id_eksponatu = NEW.id_eksponatu
      AND status IN ('magazyn', 'galeria', 'wypozyczony') AND (
          COALESCE(NEW.data_zakonczenia, '9999-12-31'::date) >= data_rozpoczecia
          AND COALESCE(data_zakonczenia, '9999-12-31'::date) >= NEW.data_rozpoczecia)
      AND (TG_OP = 'INSERT' OR id_historii <> NEW.id_historii);
    
    IF licznik > 0 THEN
        RAISE EXCEPTION 'Eksponat % ma już status w okresie, który koliduje z nowym wpisem.', NEW.id_eksponatu;
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tg_zakaz_nakladania_statusu
BEFORE INSERT OR UPDATE ON Historia
FOR EACH ROW
EXECUTE PROCEDURE zakaz_nakladania_statusu();



