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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import de.oaa.libredeck.web.model.Track;
import de.oaa.libredeck.web.service.TrackNormalizer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class DeezerApiClient {

    private static final String API_BASE   = "https://api.deezer.com";
    private static final long   RATE_LIMIT = 150; // ms – stays safely under Deezer's 50 req/5s quota

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

    private long lastRequestTime = 0;

    public String fetchPlaylistTitle(String playlistId) throws IOException {
        JsonNode root = mapper.readTree(get(API_BASE + "/playlist/" + playlistId));
        return root.path("title").asText("Playlist " + playlistId);
    }

    /** Fetches lite track stubs from the playlist (no year resolved here). */
    public List<Track> fetchTracks(String playlistId) throws IOException {
        List<Track> result = new ArrayList<>();
        String url = API_BASE + "/playlist/" + playlistId + "/tracks?limit=100";

        while (url != null) {
            JsonNode root = mapper.readTree(get(url));
            JsonNode data = root.path("data");
            if (!data.isArray()) throw new IOException("Unerwartetes Deezer-Response-Format (kein data-Array)");
            for (JsonNode node : data) {
                String rawTitle  = node.path("title").asText();
                String rawArtist = node.path("artist").path("name").asText("");
                String[] ta      = TrackNormalizer.extractFeaturing(TrackNormalizer.cleanTitle(rawTitle), rawArtist);
                result.add(new Track(
                        node.get("id").asText(),
                        ta[0],
                        ta[1],
                        "",
                        node.path("link").asText("https://www.deezer.com/track/" + node.get("id").asText())
                ));
            }
            JsonNode next = root.path("next");
            url = next.isMissingNode() || next.isNull() ? null : next.asText();
        }
        return result;
    }

    /**
     * Fetches the full track object and returns the oldest release year found
     * by comparing the track's own release_date with its album's release_date.
     * Returns an empty string if no date is available.
     */
    public String fetchTrackYear(String trackId) {
        try {
            JsonNode full      = mapper.readTree(get(API_BASE + "/track/" + trackId));
            String   trackDate = full.path("release_date").asText("");
            String   albumDate = full.path("album").path("release_date").asText("");

            String trackYear = trackDate.length() >= 4 ? trackDate.substring(0, 4) : "";
            String albumYear = albumDate.length() >= 4 ? albumDate.substring(0, 4) : "";

            if (trackYear.isEmpty() && albumYear.isEmpty()) return "";
            if (trackYear.isEmpty()) return albumYear;
            if (albumYear.isEmpty()) return trackYear;
            return trackYear.compareTo(albumYear) <= 0 ? trackYear : albumYear;
        } catch (IOException e) {
            log.warn("Could not fetch track year for {}: {}", trackId, e.getMessage());
            return "";
        }
    }

    private synchronized String get(String url) throws IOException {
        long wait = RATE_LIMIT - (System.currentTimeMillis() - lastRequestTime);
        if (wait > 0) {
            try { Thread.sleep(wait); } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new IOException("Request interrupted", e);
            }
        }
        lastRequestTime = System.currentTimeMillis();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .GET()
                .build();
        try {
            HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != 200) {
                throw new IOException("Deezer API error " + response.statusCode() + ": " + response.body());
            }
            String body = response.body();
            JsonNode root = mapper.readTree(body);
            JsonNode error = root.path("error");
            if (!error.isMissingNode() && !error.isNull()) {
                String msg  = error.path("message").asText("Unbekannter Fehler");
                int    code = error.path("code").asInt(0);
                throw new IOException("Deezer: " + msg + " (code " + code + ")");
            }
            return body;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("Request interrupted", e);
        }
    }

    // -------------------------------------------------------------------------
    // OAuth methods – commented out until Deezer re-enables app registration.
    // -------------------------------------------------------------------------
    // private static final String TOKEN_URL = "https://connect.deezer.com/oauth/access_token.php";
    //
    // public OAuthToken exchangeCode(String code, DeezerConfig config) throws IOException { ... }
    // public List<PlaylistSummary> fetchPlaylists(String accessToken) throws IOException { ... }
}
