<?php

namespace App\Services\Video;

use App\Services\GoogleCloudService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class TtsService
{
    private GoogleCloudService $googleCloud;

    public function __construct(GoogleCloudService $googleCloud)
    {
        $this->googleCloud = $googleCloud;
    }

    /**
     * 텍스트 → MP3 음성 파일 생성
     *
     * @return string|null 저장된 파일 경로
     */
    public function synthesize(string $text, string $savePath, array $options = []): ?string
    {
        $token = $this->googleCloud->getAccessToken();
        if (! $token) {
            Log::error('TtsService: 액세스 토큰 획득 실패');

            return null;
        }

        try {
            $languageCode = $options['language_code'] ?? 'ko-KR';
            $voiceName = $options['voice_name'] ?? 'ko-KR-Neural2-A';
            $speakingRate = $options['speaking_rate'] ?? 1.4;
            $pitch = $options['pitch'] ?? 0.0;

            // TTS 전송 전 이모지/특수문자 제거 (읽어버리는 문제 방지)
            $cleanText = $this->stripNonSpeechChars($text);

            $response = Http::withToken($token)
                ->timeout(30)
                ->post('https://texttospeech.googleapis.com/v1/text:synthesize', [
                    'input' => [
                        'text' => $cleanText,
                    ],
                    'voice' => [
                        'languageCode' => $languageCode,
                        'name' => $voiceName,
                    ],
                    'audioConfig' => [
                        'audioEncoding' => 'MP3',
                        'speakingRate' => $speakingRate,
                        'pitch' => $pitch,
                        'sampleRateHertz' => 24000,
                    ],
                ]);

            if (! $response->successful()) {
                Log::error('TtsService: TTS API 실패', [
                    'status' => $response->status(),
                    'body' => $response->body(),
                ]);

                return null;
            }

            $data = $response->json();
            $audioContent = $data['audioContent'] ?? null;

            if (! $audioContent) {
                Log::error('TtsService: 오디오 데이터 없음');

                return null;
            }

            $dir = dirname($savePath);
            if (! is_dir($dir)) {
                mkdir($dir, 0755, true);
            }

            file_put_contents($savePath, base64_decode($audioContent));

            Log::info('TtsService: 음성 파일 생성 완료', [
                'path' => $savePath,
                'text_length' => mb_strlen($text),
            ]);

            return $savePath;
        } catch (\Exception $e) {
            Log::error('TtsService: 예외 발생', ['error' => $e->getMessage()]);

            return null;
        }
    }

    /**
     * 장면별 일괄 나레이션 생성
     *
     * @param  array  $scenes  [{narration, scene_number}, ...]
     * @return array [scene_number => file_path, ...]
     */
    public function synthesizeScenes(array $scenes, string $baseDir): array
    {
        $results = [];

        foreach ($scenes as $scene) {
            $sceneNum = $scene['scene_number'] ?? 0;
            $narration = $scene['narration'] ?? '';

            if (empty($narration)) {
                continue;
            }

            $savePath = "{$baseDir}/narration_{$sceneNum}.mp3";
            $result = $this->synthesize($narration, $savePath);

            if ($result) {
                $results[$sceneNum] = $result;
            }
        }

        return $results;
    }

    /**
     * TTS에 보내기 전 이모지, 특수문자, 동작 표현 제거
     */
    private function stripNonSpeechChars(string $text): string
    {
        // 이모지 유니코드 블록 제거
        $text = preg_replace('/[\x{1F600}-\x{1F64F}]/u', '', $text); // 이모티콘
        $text = preg_replace('/[\x{1F300}-\x{1F5FF}]/u', '', $text); // 기호/픽토그래프
        $text = preg_replace('/[\x{1F680}-\x{1F6FF}]/u', '', $text); // 교통/지도
        $text = preg_replace('/[\x{1F900}-\x{1F9FF}]/u', '', $text); // 보충 이모지
        $text = preg_replace('/[\x{1FA00}-\x{1FA6F}]/u', '', $text); // 체스/확장
        $text = preg_replace('/[\x{1FA70}-\x{1FAFF}]/u', '', $text); // 심볼 확장
        $text = preg_replace('/[\x{2600}-\x{27BF}]/u', '', $text);   // 기타 심볼
        $text = preg_replace('/[\x{2700}-\x{27BF}]/u', '', $text);   // Dingbats
        $text = preg_replace('/[\x{FE00}-\x{FE0F}]/u', '', $text);   // 변형 선택자
        $text = preg_replace('/[\x{200D}]/u', '', $text);             // Zero Width Joiner
        $text = preg_replace('/[\x{20E3}]/u', '', $text);             // 키캡
        $text = preg_replace('/[\x{E0020}-\x{E007F}]/u', '', $text);  // 태그

        // *강조* 스타일 텍스트에서 별표만 제거 (내용은 유지)
        $text = str_replace('*', '', $text);

        // (효과음), [동작] 등 괄호 표현 제거
        $text = preg_replace('/\([^)]*\)/', '', $text);
        $text = preg_replace('/\[[^\]]*\]/', '', $text);

        // ○, ●, ◎ 등 특수 기호 제거
        $text = preg_replace('/[○●◎◇◆□■△▲▽▼★☆♡♥]/u', '', $text);

        // 연속 공백 정리
        $text = preg_replace('/\s+/', ' ', $text);

        return trim($text);
    }
}
