package kz.konturai.parser.service;

import com.fasterxml.jackson.databind.JsonNode;
import kz.konturai.parser.config.FacebookLeadProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import java.net.URI;
import java.time.Duration;

@Service
public class FacebookLeadGraphApiClient {

    private static final Logger log = LoggerFactory.getLogger(FacebookLeadGraphApiClient.class);

    private final FacebookLeadProperties properties;
    private final WebClient facebookLeadWebClient;

    public FacebookLeadGraphApiClient(
            FacebookLeadProperties properties,
            @Qualifier("facebookLeadWebClient") WebClient facebookLeadWebClient) {
        this.properties = properties;
        this.facebookLeadWebClient = facebookLeadWebClient;
    }

    public JsonNode fetchPostsPage(String afterCursor) {
        log.info("Requesting Facebook posts page. pageId={}, afterCursor={}, limit={}",
                properties.getPageId(), formatCursor(afterCursor), properties.getPostsPageSize());

        try {
            JsonNode response = facebookLeadWebClient.get()
                    .uri(URI.create(buildPostsUri(afterCursor)))
                    .retrieve()
                    .bodyToMono(JsonNode.class)
                    .block(Duration.ofMillis(properties.getTimeoutMs()));

            log.info("Facebook posts page received. postsCount={}, nextAfterCursor={}",
                    countItems(response.path("data")), extractAfterCursor(response));
            return response;
        } catch (WebClientResponseException e) {
            log.error("Facebook Graph API posts request failed. status={}, body={}",
                    e.getStatusCode().value(), e.getResponseBodyAsString());
            throw e;
        }
    }

    public JsonNode fetchCommentsPage(String postId, String afterCursor) {
        log.info("Requesting Facebook comments page. postId={}, afterCursor={}, limit={}",
                postId, formatCursor(afterCursor), properties.getCommentsPageSize());

        try {
            JsonNode response = facebookLeadWebClient.get()
                    .uri(URI.create(buildCommentsUri(postId, afterCursor)))
                    .retrieve()
                    .bodyToMono(JsonNode.class)
                    .block(Duration.ofMillis(properties.getTimeoutMs()));

            log.info("Facebook comments page received. postId={}, commentsCount={}, nextAfterCursor={}",
                    postId, countItems(response.path("data")), extractAfterCursor(response));
            return response;
        } catch (WebClientResponseException e) {
            log.error("Facebook Graph API comments request failed for post {}. status={}, body={}",
                    postId, e.getStatusCode().value(), e.getResponseBodyAsString());
            throw e;
        }
    }

    private int countItems(JsonNode node) {
        return node != null && node.isArray() ? node.size() : 0;
    }

    private String extractAfterCursor(JsonNode node) {
        String afterCursor = node.path("paging").path("cursors").path("after").asText(null);
        return StringUtils.hasText(afterCursor) ? afterCursor : "<none>";
    }

    private String buildPostsUri(String afterCursor) {
        StringBuilder uri = new StringBuilder()
                .append(graphApiBaseUrl())
                .append("/")
                .append(properties.getPageId())
                .append("/posts?fields=id")
                .append("&limit=")
                .append(properties.getPostsPageSize())
                .append("&access_token=")
                .append(properties.getAccessToken());

        if (StringUtils.hasText(afterCursor)) {
            uri.append("&after=").append(afterCursor);
        }

        return uri.toString();
    }

    private String buildCommentsUri(String postId, String afterCursor) {
        StringBuilder uri = new StringBuilder()
                .append(graphApiBaseUrl())
                .append("/")
                .append(postId)
                .append("/comments?fields=id,message,from,created_time")
                .append("&limit=")
                .append(properties.getCommentsPageSize())
                .append("&access_token=")
                .append(properties.getAccessToken());

        if (StringUtils.hasText(afterCursor)) {
            uri.append("&after=").append(afterCursor);
        }

        return uri.toString();
    }

    private String graphApiBaseUrl() {
        return "https://graph.facebook.com/" + properties.getGraphApiVersion();
    }

    private String formatCursor(String cursor) {
        return StringUtils.hasText(cursor) ? cursor : "<first-page>";
    }
}
