package com.vaessl.app.homebox;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import com.vaessl.app.connection.ConnectionEntity;
import com.vaessl.app.connection.ConnectionIdentifiable;
import com.vaessl.app.connection.ConnectionRepository;
import com.vaessl.app.connection.HomeboxConnectionEntity;
import com.vaessl.app.exception.ConnectionNotFoundException;
import com.vaessl.app.exception.RemoteApiException;
import com.vaessl.app.shared.ServiceItem;
import static com.vaessl.app.shared.Endpoint.HOMEBOX_QUERY_ALL_ITEMS;

/**
 * Fetches items from the Homebox entities API. Shared by {@code HomeboxSearchProvider} and
 * {@code HomeboxSyncProvider} so both keyword search and vector-store sync page through the same
 * remote call and item mapping.
 */
@Component
public class HomeboxItemClient {

    private final RestClient.Builder restClientBuilder;

    private final ConnectionRepository cRepository;


    public HomeboxItemClient(RestClient.Builder restClienBuilder,
            ConnectionRepository cRepository) {
        this.restClientBuilder = restClienBuilder;
        this.cRepository = cRepository;
    }

    /**
     * Fetches one page of items from Homebox for the given connection.
     *
     * @param connection identifies which stored connection (app URL, username) to query
     * @param query optional keyword filter; {@code null} returns all items for the page
     * @param pageable page number and size to request
     * @return the mapped page of items along with the resolved connection ID
     * @throws com.vaessl.app.exception.ConnectionNotFoundException if no matching connection is stored
     * @throws com.vaessl.app.exception.RemoteApiException if Homebox returns an empty response body
     */
    public HomeboxItemPage hbResponse(ConnectionIdentifiable connection, String query,
            Pageable pageable) {
        ConnectionEntity entity =
                cRepository.findByAppUrlAndUsername(connection.appUrl(), connection.username());

        if (!(entity instanceof HomeboxConnectionEntity hbEntity)) {
            throw new ConnectionNotFoundException();
        }

        HomeboxItemsResponse response = restClientBuilder.baseUrl(connection.appUrl()).build().get()
                .uri(u -> u.path(HOMEBOX_QUERY_ALL_ITEMS.getValue()).queryParam("q", query)
                        .queryParam("page", pageable.getPageNumber() + 1)
                        .queryParam("pageSize", pageable.getPageSize()).build())
                .headers(h -> h.setBearerAuth(hbEntity.getToken())).retrieve()
                .body(HomeboxItemsResponse.class);

        if (response == null) {
            throw new RemoteApiException(connection.appUrl(), HOMEBOX_QUERY_ALL_ITEMS.getValue());
        }

        List<ServiceItem> items = response.items().stream().map(i -> {
            String id = i.id();
            String title = i.name();
            String description = i.description();

            HomeboxParent parent = i.parent();
            Map<String, Object> extraData = new HashMap<>();
            if (parent.name() != null && !parent.name().isBlank()) {
                extraData.put("locationName", parent.name());
            }
            if (parent.description() != null && !parent.description().isBlank()) {
                extraData.put("locationDescription", parent.description());
            }

            return new ServiceItem(id, title, description, extraData);
        }).toList();

        return new HomeboxItemPage(new PageImpl<>(items, pageable, response.total()),
                hbEntity.getId());

    }

    public record HomeboxItemPage(Page<ServiceItem> page, Long connectionId) {
    }

    private record HomeboxItemsResponse(int page, int pageSize, int total,
            List<HomeboxItem> items) {
    }

    private record HomeboxItem(String id, String name, String description, HomeboxParent parent) {
    }

    private record HomeboxParent(String name, String description) {
    }


}
