<?php
declare(strict_types=1);

namespace App\Support;

final class TranslationService
{
    public function translate(string $text, string $targetLanguage, string $sourceLanguage = 'en'): string
    {
        $normalizedTarget = normalize_locale($targetLanguage, $sourceLanguage);
        $normalizedSource = normalize_locale($sourceLanguage, 'en');

        if ($text === '' || $normalizedTarget === $normalizedSource) {
            return $text;
        }

        $cached = $this->cached($text, $normalizedSource, $normalizedTarget);

        if ($cached !== null) {
            return $cached;
        }

        $translated = $this->requestTranslation($text, $normalizedSource, $normalizedTarget);

        if ($translated === null || $translated === '') {
            return $text;
        }

        $this->store($text, $normalizedSource, $normalizedTarget, $translated);

        return $translated;
    }

    public function translateArray(array $items, string $targetLanguage, string $sourceLanguage = 'en'): array
    {
        if ($items === []) {
            return [];
        }

        $translated = [];

        foreach ($items as $key => $value) {
            $translated[$key] = is_string($value)
                ? $this->translate($value, $targetLanguage, $sourceLanguage)
                : $value;
        }

        return $translated;
    }

    private function requestTranslation(string $text, string $sourceLanguage, string $targetLanguage): ?string
    {
        if (!config('translation_service.enabled', true)) {
            return null;
        }

        $endpoint = (string) config('translation_service.endpoint', 'https://translate.googleapis.com/translate_a/single');
        $query = http_build_query([
            'client' => 'gtx',
            'sl' => $sourceLanguage,
            'tl' => $targetLanguage,
            'dt' => 't',
            'q' => $text,
        ]);

        $context = stream_context_create([
            'http' => [
                'method' => 'GET',
                'timeout' => (int) config('translation_service.timeout', 8),
                'header' => "User-Agent: RIASEC Translation Service\r\n",
            ],
        ]);

        $response = @file_get_contents($endpoint . '?' . $query, false, $context);

        if (!is_string($response) || $response === '') {
            return null;
        }

        $payload = json_decode($response, true);

        if (!is_array($payload) || !isset($payload[0]) || !is_array($payload[0])) {
            return null;
        }

        $segments = [];

        foreach ($payload[0] as $part) {
            if (is_array($part) && isset($part[0]) && is_string($part[0])) {
                $segments[] = $part[0];
            }
        }

        return $segments === [] ? null : implode('', $segments);
    }

    private function cached(string $text, string $sourceLanguage, string $targetLanguage): ?string
    {
        $path = $this->cachePath($text, $sourceLanguage, $targetLanguage);

        if (!is_file($path)) {
            return null;
        }

        $contents = @file_get_contents($path);

        if (!is_string($contents) || $contents === '') {
            return null;
        }

        $payload = json_decode($contents, true);

        return is_array($payload) && is_string($payload['translated'] ?? null)
            ? $payload['translated']
            : null;
    }

    private function store(string $text, string $sourceLanguage, string $targetLanguage, string $translated): void
    {
        $directory = $this->cacheDirectory();

        if (!is_dir($directory)) {
            @mkdir($directory, 0777, true);
        }

        @file_put_contents(
            $this->cachePath($text, $sourceLanguage, $targetLanguage),
            json_encode([
                'source' => $sourceLanguage,
                'target' => $targetLanguage,
                'translated' => $translated,
                'updated_at' => date('c'),
            ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
        );
    }

    private function cacheDirectory(): string
    {
        return rtrim((string) config('storage.translation_cache', BASE_PATH . '/storage/translation-cache'), '/\\');
    }

    private function cachePath(string $text, string $sourceLanguage, string $targetLanguage): string
    {
        $hash = sha1($sourceLanguage . '|' . $targetLanguage . '|' . $text);

        return $this->cacheDirectory() . '/' . $hash . '.json';
    }
}