package library.routes;

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

import io.javalin.config.JavalinConfig;
import io.javalin.http.Context;
import library.domain.Book;
import library.dto.NewBook;
import library.service.BookService;

/**
 * HTTP in, HTTP out for /books.
 *
 * Each handler parses the request, calls one service method, and turns the
 * result into a status code and JSON. No SQL here.
 */
public class BookRoutes {

    private final BookService service;

    public BookRoutes(BookService service) {
        this.service = service;
    }

    // Javalin 7: called from inside Javalin.create(config -> { ... })
    public void register(JavalinConfig config) {
        config.routes.get("/books", ctx -> list(ctx));
        config.routes.get("/books/{id}", ctx -> getOne(ctx));
        config.routes.post("/books", ctx -> create(ctx));
    }

    // GET /books and GET /books?author=...
    private void list(Context ctx) throws SQLException {
        String author = ctx.queryParam("author");
        List<Book> books = (author == null) ? service.findAll() : service.findByAuthor(author);
        ctx.json(books);
    }

    // GET /books/{id}
    // A non-numeric id (GET /books/abc) still gives a 500 here.
    private void getOne(Context ctx) throws SQLException {
        int id = Integer.parseInt(ctx.pathParam("id"));
        Optional<Book> book = service.findById(id);
        if (book.isPresent()) {
            ctx.json(book.get());
        } else {
            ctx.status(404);
        }
    }

    // POST /books
    // A duplicate ISBN still gives a 500 here.
    private void create(Context ctx) throws SQLException {
        NewBook body = ctx.bodyAsClass(NewBook.class);
        try {
            Book created = service.create(body);
            ctx.status(201);
            ctx.header("Location", "/books/" + created.bookId());
            ctx.json(created);
        } catch (IllegalArgumentException e) {
            ctx.status(400).result(e.getMessage());
        }
    }
}