<?php

namespace App\Services;

use OpenAI\Client;
use OpenAI\Factory;

class TtsService
{
    protected function client(): Client
    {
        $apiKey = config('services.openai.api_key');
        if (empty($apiKey)) {
            throw new \RuntimeException('OPENAI_API_KEY is not set. Please add it to your .env file.');
        }
        return (new Factory())->withApiKey($apiKey)->make();
    }

    protected function mapLanguageForTTS(?string $langCode): string
    {
        if ($langCode === null || $langCode === '') {
            return 'en-IN';
        }
        $code = strtolower($langCode);
        if (str_starts_with($code, 'hi')) {
            return 'hi';
        }
        if (str_starts_with($code, 'mr')) {
            return 'mr';
        }
        if (str_starts_with($code, 'en')) {
            return 'en-IN';
        }
        return 'en-IN';
    }

    /**
     * Convert text to speech. Tries free Google Translate TTS first if USE_FREE_TTS is not false.
     */
    public function textToSpeech(string $text, string $language = 'en'): string
    {
        $ttsLang = $this->mapLanguageForTTS($language);

        if (config('services.voice.use_free_tts', true)) {
            try {
                return $this->textToSpeechFree($text, $ttsLang);
            } catch (\Throwable $e) {
                // Fall through to OpenAI TTS
            }
        }

        return $this->textToSpeechOpenAI($text);
    }

    protected function textToSpeechFree(string $text, string $languageCode): string
    {
        $maxLength = 200;
        $sentences = preg_split('/([^.!?]+[.!?]+)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) ?: [$text];
        $chunks = [];

        foreach ($sentences as $sentence) {
            $sentence = trim($sentence);
            if ($sentence === '') {
                continue;
            }
            if (strlen($sentence) <= $maxLength) {
                $chunks[] = $this->fetchAudioChunk($sentence, $languageCode);
            } else {
                $words = explode(' ', $sentence);
                $current = '';
                foreach ($words as $word) {
                    if (strlen($current . ' ' . $word) > $maxLength) {
                        if ($current !== '') {
                            $chunks[] = $this->fetchAudioChunk($current, $languageCode);
                        }
                        $current = $word;
                    } else {
                        $current = ($current === '') ? $word : $current . ' ' . $word;
                    }
                }
                if ($current !== '') {
                    $chunks[] = $this->fetchAudioChunk($current, $languageCode);
                }
            }
        }

        $combined = implode('', $chunks);
        return base64_encode($combined);
    }

    protected function fetchAudioChunk(string $text, string $languageCode): string
    {
        if ($text === '') {
            return '';
        }
        $url = 'https://translate.google.com/translate_tts?ie=UTF-8&tl=' . urlencode($languageCode) . '&client=tw-ob&q=' . urlencode($text);

        $client = new \GuzzleHttp\Client([
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            ],
        ]);
        $response = $client->request('GET', $url);

        if ($response->getStatusCode() !== 200) {
            throw new \RuntimeException('TTS API returned ' . $response->getStatusCode());
        }

        return (string) $response->getBody();
    }

    protected function textToSpeechOpenAI(string $text): string
    {
        $response = $this->client()->audio()->speech([
            'model' => 'tts-1',
            'voice' => 'nova',
            'input' => $text,
        ]);

        return base64_encode((string) $response->getBody());
    }
}
