<?php

namespace App\Http\Controllers\Rd;

use App\Helpers\AiTokenHelper;
use App\Http\Controllers\Controller;
use App\Models\Rd\CmSong;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class CmSongController extends Controller
{
    private string $baseUrl;

    private string $apiKey;

    public function __construct()
    {
        $this->baseUrl = config('services.gemini.base_url');
        $this->apiKey = config('services.gemini.api_key');
    }

    /**
     * 나레이션 목록
     */
    public function index(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.cm-song.index'));
        }

        $songs = CmSong::with('user')
            ->orderByDesc('created_at')
            ->paginate(20);

        return view('rd.cm-song.index', compact('songs'));
    }

    /**
     * 나레이션 제작 페이지
     */
    public function create(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.cm-song.create'));
        }

        return view('rd.cm-song.create');
    }

    /**
     * 나레이션 상세
     */
    public function show(Request $request, int $id): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.cm-song.show', $id));
        }

        $song = CmSong::with('user')->findOrFail($id);

        return view('rd.cm-song.show', compact('song'));
    }

    /**
     * 나레이션 가사 생성 (Gemini API)
     */
    public function generateLyrics(Request $request): JsonResponse
    {
        $request->validate([
            'company_name' => 'required|string|max:100',
            'industry' => 'required|string|max:200',
            'mood' => 'required|string|max:50',
            'duration' => 'required|integer|min:10|max:60',
        ]);

        $duration = $request->duration;
        $lines = match (true) {
            $duration <= 15 => '3~4줄',
            $duration <= 30 => '6~8줄',
            $duration <= 45 => '10~12줄',
            default => '14~16줄',
        };

        $prompt = "당신은 전문 나레이션 작사가입니다. 다음 정보를 바탕으로 기억에 남는 {$duration}초 분량의 라디오 나레이션 가사를 작성해주세요.

회사명: {$request->company_name}
업종/제품: {$request->industry}
분위기: {$request->mood}

조건:
- {$lines}로 작성 ({$duration}초 분량)
- 운율을 살려서 작성
- 지시문(예: (음악 소리), (밝은 목소리로)) 없이 오직 읽을 수 있는 가사 텍스트만 출력할 것.";

        try {
            $response = Http::timeout(30)->post(
                "{$this->baseUrl}/models/gemini-2.5-flash:generateContent?key={$this->apiKey}",
                [
                    'contents' => [
                        ['parts' => [['text' => $prompt]]],
                    ],
                ]
            );

            if (! $response->successful()) {
                return response()->json([
                    'success' => false,
                    'error' => '가사 생성에 실패했습니다: '.$response->status(),
                ], 500);
            }

            $data = $response->json();

            // 토큰 사용량 기록
            AiTokenHelper::saveGeminiUsage($data, 'gemini-2.5-flash', '나레이션-가사생성');

            $text = $data['candidates'][0]['content']['parts'][0]['text'] ?? '';

            return response()->json([
                'success' => true,
                'lyrics' => trim($text),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => '가사 생성 중 오류: '.$e->getMessage(),
            ], 500);
        }
    }

    /**
     * TTS 음성 생성 (Gemini TTS API)
     */
    public function generateAudio(Request $request): JsonResponse
    {
        $request->validate([
            'lyrics' => 'required|string|max:2000',
        ]);

        try {
            $response = Http::timeout(60)->post(
                "{$this->baseUrl}/models/gemini-2.5-flash-preview-tts:generateContent?key={$this->apiKey}",
                [
                    'contents' => [
                        ['parts' => [['text' => $request->lyrics]]],
                    ],
                    'generationConfig' => [
                        'responseModalities' => ['AUDIO'],
                        'speechConfig' => [
                            'voiceConfig' => [
                                'prebuiltVoiceConfig' => [
                                    'voiceName' => 'Kore',
                                ],
                            ],
                        ],
                    ],
                ]
            );

            if (! $response->successful()) {
                return response()->json([
                    'success' => false,
                    'error' => '음성 생성에 실패했습니다: '.$response->status(),
                ], 500);
            }

            $data = $response->json();

            // 토큰 사용량 기록
            AiTokenHelper::saveGeminiUsage($data, 'gemini-2.5-flash-preview-tts', '나레이션-TTS');

            $inlineData = $data['candidates'][0]['content']['parts'][0]['inlineData'] ?? null;

            if (! $inlineData || empty($inlineData['data'])) {
                return response()->json([
                    'success' => false,
                    'error' => '음성 데이터를 받지 못했습니다.',
                ], 500);
            }

            return response()->json([
                'success' => true,
                'audio_data' => $inlineData['data'],
                'mime_type' => $inlineData['mimeType'] ?? 'audio/L16;rate=24000',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => '음성 생성 중 오류: '.$e->getMessage(),
            ], 500);
        }
    }

    /**
     * 나레이션 저장
     */
    public function store(Request $request): JsonResponse
    {
        $request->validate([
            'company_name' => 'required|string|max:100',
            'industry' => 'required|string|max:200',
            'mood' => 'required|string|max:50',
            'duration' => 'required|integer|min:10|max:60',
            'lyrics' => 'required|string|max:2000',
            'audio_data' => 'nullable|string',
            'audio_mime_type' => 'nullable|string',
        ]);

        $tenantId = session('selected_tenant_id', 1);
        $userId = Auth::id();
        $audioPath = null;

        // 오디오 데이터가 있으면 WAV 파일로 저장
        if ($request->audio_data) {
            $mimeType = $request->audio_mime_type ?? 'audio/L16;rate=24000';
            $audioBytes = base64_decode($request->audio_data);

            if (str_contains($mimeType, 'L16') || str_contains($mimeType, 'pcm')) {
                $sampleRate = 24000;
                if (preg_match('/rate=(\d+)/', $mimeType, $m)) {
                    $sampleRate = (int) $m[1];
                }
                $audioBytes = $this->pcmToWav($audioBytes, $sampleRate);
            }

            $filename = 'cm-song-'.date('Ymd-His').'-'.uniqid().'.wav';
            $dir = "cm-songs/{$tenantId}";
            Storage::disk('tenant')->makeDirectory($dir);
            Storage::disk('tenant')->put("{$dir}/{$filename}", $audioBytes);
            $audioPath = "{$dir}/{$filename}";
        }

        $song = CmSong::create([
            'tenant_id' => $tenantId,
            'user_id' => $userId,
            'company_name' => $request->company_name,
            'industry' => $request->industry,
            'lyrics' => $request->lyrics,
            'audio_path' => $audioPath,
            'options' => [
                'mood' => $request->mood,
                'duration' => $request->duration,
            ],
        ]);

        return response()->json([
            'success' => true,
            'id' => $song->id,
            'message' => '나레이션이 저장되었습니다.',
        ]);
    }

    /**
     * 음성 파일 다운로드
     */
    public function download(int $id)
    {
        $song = CmSong::findOrFail($id);

        if (! $song->audio_path || ! Storage::disk('tenant')->exists($song->audio_path)) {
            abort(404, '음성 파일이 없습니다.');
        }

        $filename = "나레이션_{$song->company_name}_".date('Ymd', strtotime($song->created_at)).'.wav';

        return Storage::disk('tenant')->download($song->audio_path, $filename);
    }

    /**
     * 나레이션 삭제
     */
    public function destroy(int $id): JsonResponse
    {
        $song = CmSong::findOrFail($id);

        if ($song->audio_path && Storage::disk('tenant')->exists($song->audio_path)) {
            Storage::disk('tenant')->delete($song->audio_path);
        }

        $song->delete();

        return response()->json([
            'success' => true,
            'message' => '나레이션이 삭제되었습니다.',
        ]);
    }

    /**
     * PCM → WAV 변환 (서버사이드)
     */
    private function pcmToWav(string $pcmData, int $sampleRate): string
    {
        $numChannels = 1;
        $bitsPerSample = 16;
        $byteRate = $sampleRate * $numChannels * $bitsPerSample / 8;
        $blockAlign = $numChannels * $bitsPerSample / 8;
        $dataSize = strlen($pcmData);

        $header = pack('A4VVA4', 'RIFF', 36 + $dataSize, 0x45564157, 'WAVEfmt ');
        // 'WAVE' as little-endian is 0x45564157... actually let me write it properly
        $header = 'RIFF';
        $header .= pack('V', 36 + $dataSize);
        $header .= 'WAVE';
        $header .= 'fmt ';
        $header .= pack('V', 16); // SubChunk1Size
        $header .= pack('v', 1);  // AudioFormat (PCM)
        $header .= pack('v', $numChannels);
        $header .= pack('V', $sampleRate);
        $header .= pack('V', $byteRate);
        $header .= pack('v', $blockAlign);
        $header .= pack('v', $bitsPerSample);
        $header .= 'data';
        $header .= pack('V', $dataSize);

        return $header.$pcmData;
    }
}
