```sql
USE biblioteca_fc;


DESC Funcionario;
DESC Genero;
DESC Livro;
DESC LivroInfo;
DESC LivroInfoGenero;
DESC Multa;
DESC Requisicao;
DESC Reserva;
DESC Utilizador;

SELECT * FROM Funcionario;
SELECT * FROM Genero;
SELECT * FROM Livro;
SELECT * FROM Exemplar;
SELECT * FROM LivroGenero;
SELECT * FROM Multa;
SELECT * FROM Requisicao;
SELECT * FROM Reserva;
SELECT * FROM Utilizador;

SHOW TABLES;

-- Obter a lista de funcionários atuais

SELECT * FROM Funcionario
	WHERE dta_fim_servico IS NULL;
    
-- Obter os livros que estão atualmente emprestados

SELECT * FROM Livro
	WHERE disponibilidade = 'I';

-- Obter as reservas feitas 

SELECT * FROM Reserva;

-- Obter multas aplicadas de um dado cliente

DELIMITER //
CREATE PROCEDURE multasCliente(id int)
BEGIN
	SELECT * FROM Multa m INNER JOIN Requisicao r ON m.Requisicao=r.Utilizador
		WHERE r.Utilizador=id;
END 
// DELIMITER ;

-- CALL multasCliente(2);

-- Obter o histórico de requisições de um determinado utilizador

DELIMITER //
CREATE PROCEDURE requisicoesCliente(id int)
BEGIN
	SELECT * FROM Requisicao
		WHERE Utilizador=id
			ORDER BY `data` DESC;
END 
// DELIMITER ;

-- CALL requisicoesCliente(2);


-- Saber quais os géneros mais requisitados.

SELECT g.descricao,COUNT(g.descricao) AS nr_ocorrencias FROM Genero g 
	INNER JOIN LivroGenero lg ON g.id=lg.Genero
		INNER JOIN Livro l ON l.ISBN=lg.Livro
			INNER JOIN Exemplar e ON e.Livro=l.ISBN
				INNER JOIN Requisicao r ON r.Exemplar=e.id
					GROUP BY g.descricao
						ORDER BY nr_ocorrencias DESC;
                    
-- Se um livro for devolvido numa condição inferior à emprestada, deve ser aplicada uma multa

DELIMITER //
CREATE PROCEDURE multaDano(idRequisicao int,montante decimal(8,2))
BEGIN
	INSERT INTO Multa(`montante`, `tipo`, `Requisicao`) VALUES
		(montante, 'D', idRequisicao);
END 
// DELIMITER ;

-- CALL requisicoesCliente(1, 5.5);

-- Realizar a reserva de um livro

DELIMITER //
CREATE PROCEDURE reservaLivro(idUser int,idLivro int)
BEGIN
	INSERT INTO Reserva(`data`,`Utilizador`, `Livro`) VALUES
		(CURDATE(), idUser, idLivro);
END 
// DELIMITER ;

-- Registo de uma requisicao

DELIMITER //
CREATE PROCEDURE registaRequisicao(idUser int,idFuncionario int, idExemplar int)
BEGIN
	INSERT INTO Requisicao(`data`,`Utilizador`, `Funcionario`,`Exemplar`) VALUES
		(CURDATE(), idUser, idFuncionario, idExemplar);
END 
// DELIMITER ;

-- CALL registaRequisicao(1,1,1);


-- Utilizadores mais ativos da biblioteca

SELECT u.nome, COUNT(r.Utilizador) AS `Número de Requisições` 
	FROM Requisicao r INNER JOIN Utilizador u ON u.id=r.Utilizador
		GROUP BY r.Utilizador
			ORDER BY `Número de Requisições` DESC;
    

-- Funcionários mais ativos da biblioteca

SELECT f.nome, COUNT(r.Funcionario) AS `Número de Requisições Registadas`
	FROM Requisicao r INNER JOIN Funcionario f ON f.id=r.Funcionario
		GROUP BY r.Funcionario
			ORDER BY `Número de Requisições Registadas` DESC;
    
-- Lista de livro mais populares da biblioteca

SELECT TOTAL.titulo AS `Título`, TOTAL.Exemplares + TOTAL.Reservas AS Popularidade FROM 
(
		SELECT l.titulo, COUNT(req.Exemplar) AS Exemplares, COUNT(res.Livro) AS Reservas
			FROM Requisicao req
				INNER JOIN Exemplar e ON req.Exemplar = e.id
					INNER JOIN Livro l ON l.ISBN = e.Livro
						LEFT JOIN Reserva res ON res.Livro = l.ISBN
							GROUP BY e.Livro
) AS TOTAL ORDER BY Popularidade DESC;


-- Entrega de um Livro (O estado do livro é atualizado por um trigger)

DELIMITER //
CREATE PROCEDURE registaEntrega(idUser int,idFuncionario int, idExemplar int)
BEGIN
	UPDATE Requisicao r
		SET r.estado='C'
			WHERE r.Utilizador=idUser 
				AND r.Funcionario=idFuncionario 
					AND r.Exemplar=idExemplar;
END 
// DELIMITER ;

SHOW INDEXES FROM Livro;

-- CALL registaEntrega(1,1,1);

    ```