package de.oaa.libredeck.web.service.spotify;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.oaa.libredeck.web.config.SpotifyConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Slf4j
@Component
@RequiredArgsConstructor
public class SpotifyTokenRefresher {

    private static final String TOKEN_URL = "https://accounts.spotify.com/api/token";

    private final SpotifyConfig     config;
    private final SpotifyTokenStore tokenStore;

    private final HttpClient   http   = HttpClient.newHttpClient();
    private final ObjectMapper mapper = new ObjectMapper();

    /** Attempts to refresh the access token. Returns true if the token is now valid. */
    public boolean tryRefresh() {
        String refreshToken = tokenStore.getRefreshToken();
        if (refreshToken == null || refreshToken.isBlank()) return false;

        try {
            String credentials = Base64.getEncoder().encodeToString(
                    (config.getClientId() + ":" + config.getClientSecret()).getBytes(StandardCharsets.UTF_8));

            HttpRequest req = HttpRequest.newBuilder()
                    .uri(URI.create(TOKEN_URL))
                    .header("Authorization", "Basic " + credentials)
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .POST(HttpRequest.BodyPublishers.ofString(
                            "grant_type=refresh_token&refresh_token="
                            + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8)))
                    .build();

            HttpResponse<String> resp = http.send(req, HttpResponse.BodyHandlers.ofString());
            JsonNode json = mapper.readTree(resp.body());

            if (json.has("error")) {
                log.warn("Spotify token refresh failed: {}", resp.body());
                return false;
            }

            tokenStore.setAccessToken(json.path("access_token").asText());
            int expiresIn = json.path("expires_in").asInt(3600);
            tokenStore.setExpiresAt(System.currentTimeMillis() + (expiresIn - 60) * 1000L);

            // Spotify may return a new refresh token
            String newRefresh = json.path("refresh_token").asText("");
            if (!newRefresh.isBlank()) tokenStore.setRefreshToken(newRefresh);

            log.info("Spotify token refreshed, expires in {}s", expiresIn);
            return true;

        } catch (Exception e) {
            log.warn("Spotify token refresh error: {}", e.getMessage());
            return false;
        }
    }
}
