package pl.polskalokalnie.i18n;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
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.time.Duration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import pl.polskalokalnie.user.PreferredLanguage;

@Service
public class RuntimeTranslationService {

    private static final int MAX_TEXTS_PER_REQUEST = 180;
    private static final int MAX_TEXT_LENGTH = 400;

    private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(6))
            .build();
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final Map<String, String> cache = new ConcurrentHashMap<>();

    public Map<String, String> translateBatch(PreferredLanguage language, List<String> texts) {
        if (texts == null || texts.isEmpty()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Brak tekstów do tłumaczenia");
        }
        if (texts.size() > MAX_TEXTS_PER_REQUEST) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Zbyt wiele tekstów do tłumaczenia w jednym żądaniu");
        }

        if (language == PreferredLanguage.PL) {
            Map<String, String> passthrough = new LinkedHashMap<>();
            texts.forEach((text) -> passthrough.put(text, text));
            return passthrough;
        }

        String targetCode = toGoogleLang(language);
        Map<String, String> results = new LinkedHashMap<>();
        List<String> toTranslate = new ArrayList<>();

        for (String text : texts) {
            String safeText = text != null ? text : "";
            if (safeText.length() > MAX_TEXT_LENGTH) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Jeden z tekstów jest zbyt długi do tłumaczenia");
            }

            String cacheKey = targetCode + "|" + safeText;
            String cached = cache.get(cacheKey);
            if (cached != null) {
                results.put(safeText, cached);
            } else {
                toTranslate.add(safeText);
            }
        }

        for (String text : toTranslate) {
            String translated = translateSingle(text, targetCode);
            cache.put(targetCode + "|" + text, translated);
            results.put(text, translated);
        }

        return results;
    }

    private String translateSingle(String source, String targetCode) {
        if (source.isBlank()) {
            return source;
        }

        String encoded = URLEncoder.encode(source, StandardCharsets.UTF_8);
        String url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=pl&tl="
                + targetCode + "&dt=t&q=" + encoded;

        HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                .GET()
                .timeout(Duration.ofSeconds(10))
                .header("Accept", "application/json")
                .header("User-Agent", "PolskaLokalnie/1.0")
                .build();

        try {
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() < 200 || response.statusCode() >= 300) {
                throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "Usługa tłumaczeń jest chwilowo niedostępna");
            }
            return parseTranslatedText(response.body(), source);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "Nie udało się pobrać tłumaczenia", ex);
        } catch (IOException ex) {
            throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "Nie udało się pobrać tłumaczenia", ex);
        }
    }

    private String parseTranslatedText(String payload, String fallback) throws IOException {
        JsonNode root = objectMapper.readTree(payload);
        JsonNode topSegments = root.path(0);
        if (!topSegments.isArray() || topSegments.isEmpty()) {
            return fallback;
        }
        StringBuilder translated = new StringBuilder();
        for (JsonNode segment : topSegments) {
            JsonNode part = segment.path(0);
            if (part.isTextual()) {
                translated.append(part.asText());
            }
        }
        String value = translated.toString();
        return value.isBlank() ? fallback : value;
    }

    private String toGoogleLang(PreferredLanguage language) {
        return switch (language) {
            case EN -> "en";
            case UK -> "uk";
            case DE -> "de";
            case PL -> "pl";
        };
    }
}
