
CREATE TABLE Artysta (
    ID serial PRIMARY KEY,
    imie varchar(30)  NOT NULL,
    nazwisko varchar(50) NOT NULL,
    rok_ur date  NOT NULL CHECK (rok_ur < current_date),
    rok_smierci date CHECK (rok_smierci IS NULL OR rok_smierci > rok_ur)
);

CREATE TABLE Eksponat (
    ID serial PRIMARY KEY,
    tytul  varchar(50)  NOT NULL,
    typ varchar(30)  NOT NULL,
    wysokosc  decimal(4,2) CHECK (wysokosc > 0),
    szerokosc decimal(4,2) CHECK (szerokosc > 0),
    waga decimal(6,2) CHECK (waga > 0),
    artysta_ID int references Artysta,
    czy_w_magazynie boolean  NOT NULL,
    czy_cenny boolean  NOT NULL
);

CREATE TABLE Galeria (
    ID int PRIMARY KEY,
    nazwa varchar(50) NOT NULL
);

CREATE TABLE Ekspozycja (
    ID serial PRIMARY KEY,
    Eksponat_ID int references Eksponat,
    Galeria_ID int references Galeria,
    nr_sali int  NOT NULL CHECK (nr_sali > 0),
    dat_wys date  NOT NULL,
    dat_zdj date  NOT NULL CHECK (dat_zdj > dat_wys)
);

CREATE TABLE Instytucja (
    ID int PRIMARY KEY,
    nazwa varchar(50) NOT NULL,
    miasto varchar(30)  NOT NULL
);

CREATE TABLE Wypozyczenie (
    ID serial PRIMARY KEY,
    Instytucja_ID int references Instytucja,
    Eksponat_ID int references Eksponat,
    dat_wyp date  NOT NULL,
    termin_zwr date  NOT NULL CHECK (termin_zwr > dat_wyp) CHECK (termin_zwr - dat_wyp <= 30),
    czy_zwr boolean  NOT NULL
);



CREATE OR REPLACE FUNCTION sprawdz_cenne() RETURNS TRIGGER AS $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM Eksponat e
        WHERE e.ID = NEW.Eksponat_ID
        AND e.czy_cenny = true
    ) THEN
        RAISE EXCEPTION 'Cenne eksponaty nie mogą być wypożyczane';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER sprawdz_cenne_trigger
BEFORE INSERT OR UPDATE ON Wypozyczenie
FOR EACH ROW
EXECUTE FUNCTION sprawdz_cenne();



CREATE OR REPLACE FUNCTION sprawdz_dni_wypozyczenia() RETURNS TRIGGER AS $$
DECLARE
    suma_dni INTEGER;
BEGIN
    SELECT COALESCE(SUM(termin_zwr - dat_wyp), 0)
    INTO suma_dni
    FROM Wypozyczenie
    WHERE Eksponat_ID = NEW.Eksponat_ID
    AND EXTRACT(YEAR FROM dat_wyp) = EXTRACT(YEAR FROM NEW.dat_wyp)
    AND ID != NEW.ID;  -- wykluczamy aktualne wypożyczenie
    
    IF (suma_dni + (NEW.termin_zwr - NEW.dat_wyp)) > 30 THEN
        RAISE EXCEPTION 'Suma dni wypożyczeń eksponatu w roku nie może przekraczać 30';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER sprawdz_dni_wypozyczenia_trigger
BEFORE INSERT OR UPDATE ON Wypozyczenie
FOR EACH ROW
EXECUTE FUNCTION sprawdz_dni_wypozyczenia();



CREATE OR REPLACE FUNCTION jeden_eksponat_kazdego_artysty() RETURNS TRIGGER AS $$
DECLARE
    liczba_eksponatow INTEGER;
BEGIN
    SELECT COUNT(*) INTO liczba_eksponatow
    FROM Eksponat e
    WHERE e.artysta_ID = OLD.artysta_ID
    AND (
        e.czy_w_magazynie = TRUE
        OR e.ID IN (SELECT Eksponat_ID FROM Ekspozycja WHERE dat_zdj >= current_date)
    );
    
    IF liczba_eksponatow = 0 THEN
        RAISE EXCEPTION 'Muzeum musi mieć co najmniej jeden eksponat każdego artysty w galerii lub magazynie';
    END IF;
    RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER jeden_eksponat_kazdego_artysty_trigger
BEFORE UPDATE OR DELETE ON Eksponat
FOR EACH ROW
EXECUTE FUNCTION jeden_eksponat_kazdego_artysty();



CREATE OR REPLACE FUNCTION zmiana_lokalizacji(
   eksponat_id INTEGER,
   aktualne_miejsce VARCHAR,
   docelowe_miejsce VARCHAR,
   parametry_dodatkowe JSONB
)
RETURNS VOID AS $$
BEGIN

   IF aktualne_miejsce = 'magazyn' THEN
      IF NOT EXISTS (
         SELECT 1
         FROM Eksponat
         WHERE ID = eksponat_id 
         AND czy_w_magazynie = TRUE
      ) THEN
         RAISE EXCEPTION 'Eksponat nie znajduje się w magazynie';
      END IF;
      
      UPDATE Eksponat
      SET czy_w_magazynie = FALSE
      WHERE ID = eksponat_id;
      
   ELSIF aktualne_miejsce = 'instytucja' THEN
      IF NOT EXISTS (
         SELECT 1
         FROM Wypozyczenie
         WHERE Eksponat_ID = eksponat_id 
         AND Instytucja_ID = (parametry_dodatkowe->>'instytucja_id')::INTEGER
         AND czy_zwr = FALSE
      ) THEN
         RAISE EXCEPTION 'Eksponat nie znajduje się w instytucji';
      END IF;
      
      UPDATE Wypozyczenie
      SET czy_zwr = TRUE
      WHERE Eksponat_ID = eksponat_id AND czy_zwr = FALSE;
      
   ELSIF aktualne_miejsce = 'galeria' THEN
      IF NOT EXISTS (
         SELECT 1
         FROM Ekspozycja
         WHERE Eksponat_ID = eksponat_id 
         AND Galeria_ID = (parametry_dodatkowe->>'galeria_id')::INTEGER
         AND dat_zdj > CURRENT_DATE
      ) THEN
         RAISE EXCEPTION 'Eksponat nie znajduje się w galerii';
      END IF;
      
      UPDATE Ekspozycja
      SET dat_zdj = CURRENT_DATE
      WHERE Eksponat_ID = eksponat_id 
      AND dat_zdj > CURRENT_DATE;
      
   ELSE
      RAISE EXCEPTION 'Nieznane miejsce przebywania eksponatu';
   END IF;

   IF docelowe_miejsce = 'magazyn' THEN
      UPDATE Eksponat
      SET czy_w_magazynie = TRUE
      WHERE ID = eksponat_id;
      
   ELSIF docelowe_miejsce = 'instytucja' THEN
      INSERT INTO Wypozyczenie (
         Instytucja_ID,
         Eksponat_ID,
         dat_wyp,
         termin_zwr,
         czy_zwr
      )
      VALUES (
         (parametry_dodatkowe->>'instytucja_id')::INTEGER,
         eksponat_id,
         CURRENT_DATE,
         CURRENT_DATE + INTERVAL '30 day',
         FALSE
      );
      
   ELSIF docelowe_miejsce = 'galeria' THEN
      INSERT INTO Ekspozycja (
         Eksponat_ID,
         Galeria_ID,
         nr_sali,
         dat_wys,
         dat_zdj
      )
      VALUES (
         eksponat_id,
         (parametry_dodatkowe->>'galeria_id')::INTEGER,
         (parametry_dodatkowe->>'nr_sali')::INTEGER,
         CURRENT_DATE,
         CURRENT_DATE + INTERVAL '90 day' -- Domyślny okres ekspozycji
      );
      
   ELSE
      RAISE EXCEPTION 'Nieznane miejsce docelowe';
   END IF;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION usuwanie_artysty()
RETURNS TRIGGER AS $$
BEGIN
    DELETE FROM Artysta 
    WHERE ID = OLD.artysta_ID 
    AND NOT EXISTS (SELECT 1 FROM Eksponat WHERE artysta_ID = OLD.artysta_ID);
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER usuwanie_artysty_trigger
AFTER DELETE ON Eksponat
FOR EACH ROW
EXECUTE FUNCTION usuwanie_artysty();



CREATE OR REPLACE FUNCTION wpisanie_eksponatu(
    tytul VARCHAR(50),
    typ VARCHAR(30),
    wysokosc DECIMAL(2,2),
    szerokosc DECIMAL(2,2),
    waga DECIMAL(4,2),
    artysta_ID INT DEFAULT NULL,
    czy_cenny BOOLEAN DEFAULT FALSE
) RETURNS VOID AS $$
DECLARE
    artysta_istnieje INT;
BEGIN
    IF artysta_ID IS NOT NULL THEN
        SELECT COUNT(*) INTO artysta_istnieje FROM Artysta WHERE ID = artysta_ID;
        IF artysta_istnieje = 0 THEN
            RAISE EXCEPTION 'Artysta nie istnieje';
        END IF;
    END IF;

    INSERT INTO Eksponat (tytul, typ, wysokosc, szerokosc, waga, artysta_ID, czy_w_magazynie, czy_cenny)
    VALUES (tytul, typ, wysokosc, szerokosc, waga, artysta_ID, TRUE, czy_cenny);
END;
$$ LANGUAGE plpgsql;





