package org.bookstore.catalog.integration;

import org.bookstore.catalog.dto.Identifier;
import org.bookstore.catalog.dto.ImageLinks;
import org.bookstore.catalog.dto.Price;
import org.bookstore.catalog.dto.SaleInfo;
import org.bookstore.catalog.dto.Volume;
import org.bookstore.catalog.dto.VolumeInfo;
import org.bookstore.catalog.entity.Book;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Optional;

@Component
public class VolumeBookConverter implements Converter<Volume, Book> {

	@Override
	public Book convert(Volume volume) {
		Book book = new Book();
		VolumeInfo volumeInfo = volume.volumeInfo();
		book.setIsbn(getIsbn(volumeInfo));
		book.setTitle(volumeInfo.title());
		book.setSubtitle(volumeInfo.subtitle());
		book.setAuthors(getAuthors(volumeInfo));
		book.setPublisher(volumeInfo.publisher());
		book.setPublicationYear(getPublicationYear(volumeInfo));
		book.setNumberOfPages(volumeInfo.pageCount());
		book.setDescription(volumeInfo.description());
		book.setImageUrl(getImageUrl(volumeInfo));
		book.setPrice(getPrice(volume.saleInfo()));
		return book;
	}

	private String getIsbn(VolumeInfo info) {
		return Optional.ofNullable(info.industryIdentifiers())
				.flatMap(identifiers -> Arrays.stream(identifiers).filter(id -> id.type().equals("ISBN_10"))
						.findFirst().map(Identifier::identifier))
				.orElse(null);
	}

	private String getAuthors(VolumeInfo info) {
		return Optional.ofNullable(info.authors()).map(authors -> String.join(", ", authors)).orElse(null);
	}

	private Integer getPublicationYear(VolumeInfo info) {
		return Optional.ofNullable(info.publishedDate())
				.map(date -> date.substring(0, 4)).map(Integer::parseInt).orElse(null);
	}

	private String getImageUrl(VolumeInfo info) {
		return Optional.ofNullable(info.imageLinks()).map(ImageLinks::thumbnail).orElse(null);
	}

	private BigDecimal getPrice(SaleInfo info) {
		return Optional.ofNullable(info.listPrice()).map(Price::amount).orElse(null);
	}
}
