package library.service;

import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

import library.dao.BookDao;
import library.domain.Book;
import library.dto.NewBook;

/**
 * Business rules for books.
 *
 * Speaks in domain terms (Book, Optional, exceptions), never HTTP status codes.
 * The error handling is deliberately simple: IllegalArgumentException for
 * bad input, Optional for "might not exist".
 */
public class BookService {

	private final BookDao dao;

	public BookService(BookDao dao) {
		this.dao = dao;
	}

	public List<Book> findAll() throws SQLException {
		return dao.findAll();
	}

	public List<Book> findByAuthor(String author) throws SQLException {
		return dao.findByAuthor(author);
	}

	public Optional<Book> findById(int id) throws SQLException {
		return dao.findById(id);
	}

	public Book create(NewBook nb) throws SQLException {
		validate(nb);
		Book book = new Book(null, nb.isbn(), nb.title(), nb.author(), nb.publishedOn(), nb.replacementCost(), true);
		int id = dao.insert(book);
		// Re-read: the stored row includes the default for available
		Optional<Book> created = dao.findById(id);
		if (created.isEmpty()) {
			throw new IllegalStateException("Book " + id + " was inserted but can't be found");
		}
		return created.get();
	}

	// PUT /books/{id} (librarians only) → the updated book, or empty if no
	// such book.
	// available isn't in NewBook, and BookDao.update leaves it alone.
	public Optional<Book> update(int id, NewBook nb) throws SQLException {
		validate(nb);
		Book book = new Book(id, nb.isbn(), nb.title(), nb.author(), nb.publishedOn(), nb.replacementCost(), true);
		if (!dao.update(book)) {
			return Optional.empty();
		}
		return dao.findById(id);
	}

	// DELETE /books/{id} (librarians only) → false if no such book.
	// A book with loan history still gives a 500 (error 1451)
	public boolean delete(int id) throws SQLException {
		return dao.delete(id);
	}

	private static void validate(NewBook nb) {
		if (nb.title() == null || nb.title().isBlank()) {
			throw new IllegalArgumentException("title is required");
		}
	}
}
