<?php
/**
 * Studio TTS Téléphone — endpoints AJAX
 */
declare(strict_types=1);
require __DIR__ . '/auth.php';
require_auth_api();

@set_time_limit(180);
$action = $_GET['action'] ?? $_POST['action'] ?? '';

try {
    switch ($action) {

        /* ----- Configuration ----- */
        case 'get_config': {
            $c = cfg_load();
            $key = (string) $c['api_key'];
            json_out([
                'ok'           => true,
                'has_key'      => $key !== '',
                'key_masked'   => $key !== '' ? '••••••••' . substr($key, -4) : '',
                'model_id'     => $c['model_id'],
                'stability'    => $c['stability'],
                'similarity'   => $c['similarity'],
                'style'        => $c['style'],
                'speaker_boost'=> $c['speaker_boost'],
                'music_volume' => $c['music_volume'],
                'intro'        => $c['intro'],
                'tail'         => $c['tail'],
                'ducking'      => $c['ducking'],
                'has_cookies'  => is_file(COOKIES_FILE),
            ]);
        }

        /* ----- Cookies YouTube (cookies.txt Netscape) ----- */
        case 'upload_cookies': {
            if (empty($_FILES['cookies']) || $_FILES['cookies']['error'] !== UPLOAD_ERR_OK) {
                fail('Aucun fichier reçu.');
            }
            $data = (string) file_get_contents($_FILES['cookies']['tmp_name']);
            if (stripos($data, 'youtube.com') === false && stripos($data, '# Netscape') === false && substr_count($data, "\t") < 3) {
                fail('Ce fichier ne ressemble pas à un cookies.txt (format Netscape) YouTube.');
            }
            file_put_contents(COOKIES_FILE, $data, LOCK_EX);
            @chmod(COOKIES_FILE, 0600);
            json_out(['ok' => true]);
        }

        case 'delete_cookies': {
            @unlink(COOKIES_FILE);
            json_out(['ok' => true]);
        }

        case 'save_config': {
            $c = cfg_load();
            $key = trim((string) ($_POST['api_key'] ?? ''));
            if ($key !== '' && strpos($key, '•') === false) {
                $c['api_key'] = $key;        // n'écrase pas si champ laissé masqué
            }
            foreach (['stability','similarity','style','music_volume','intro','tail'] as $f) {
                if (isset($_POST[$f]) && $_POST[$f] !== '') {
                    $c[$f] = (float) $_POST[$f];
                }
            }
            if (isset($_POST['model_id']) && $_POST['model_id'] !== '') {
                $c['model_id'] = preg_replace('/[^a-z0-9_]/i', '', (string) $_POST['model_id']);
            }
            $c['speaker_boost'] = !empty($_POST['speaker_boost']) && $_POST['speaker_boost'] !== 'false';
            $c['ducking']       = !empty($_POST['ducking']) && $_POST['ducking'] !== 'false';
            cfg_save($c);

            // Changement éventuel du mot de passe d'accès
            $newPw = (string) ($_POST['app_password'] ?? '');
            if ($newPw !== '') {
                if (strlen($newPw) < 4) {
                    fail('Le mot de passe doit faire au moins 4 caractères.');
                }
                app_set_password($newPw);
            }
            json_out(['ok' => true]);
        }

        /* ----- Voix ----- */
        case 'voices': {
            json_out(['ok' => true, 'voices' => el_voices()]);
        }

        /* ----- Solde / quota du compte ElevenLabs ----- */
        case 'quota': {
            $r = el_request('GET', '/v1/user/subscription');
            if ($r['code'] !== 200) {
                $msg = el_error_msg($r['body']) ?? ('HTTP ' . $r['code']);
                fail('Solde indisponible : ' . $msg, 502);
            }
            $d     = json_decode($r['body'], true) ?: [];
            $used  = (int) ($d['character_count'] ?? 0);
            $limit = (int) ($d['character_limit'] ?? 0);
            json_out([
                'ok'        => true,
                'used'      => $used,
                'limit'     => $limit,
                'remaining' => max(0, $limit - $used),
                'tier'      => (string) ($d['tier'] ?? ''),
                'reset'     => $d['next_character_count_reset_unix'] ?? null,
            ]);
        }

        /* ----- Test d'une voix → mp3 direct ----- */
        case 'test_voice': {
            $c       = cfg_load();
            $voiceId = (string) ($_POST['voice_id'] ?? '');
            $text    = trim((string) ($_POST['text'] ?? ''));
            if ($text === '') {
                $text = "Bonjour et bienvenue. Vous êtes en relation avec notre standard, votre appel est important pour nous.";
            }
            $settings = [
                'stability'     => $_POST['stability']     ?? $c['stability'],
                'similarity'    => $_POST['similarity']    ?? $c['similarity'],
                'style'         => $_POST['style']         ?? $c['style'],
                'speaker_boost' => isset($_POST['speaker_boost']) ? ($_POST['speaker_boost'] !== 'false') : $c['speaker_boost'],
            ];
            $r = el_tts_file($voiceId, $text, $settings, $c['model_id']);
            header('Content-Type: audio/mpeg');
            header('Content-Length: ' . filesize($r['path']));
            header('X-Cache: ' . ($r['cached'] ? 'hit' : 'miss'));
            readfile($r['path']);
            exit;
        }

        /* ----- Upload d'une musique ----- */
        case 'upload_music': {
            if (empty($_FILES['music']) || $_FILES['music']['error'] !== UPLOAD_ERR_OK) {
                fail('Aucun fichier reçu.');
            }
            $f   = $_FILES['music'];
            if ($f['size'] > 60 * 1024 * 1024) {
                fail('Fichier trop volumineux (max 60 Mo).');
            }
            $ext = strtolower(pathinfo($f['name'], PATHINFO_EXTENSION));
            if (!in_array($ext, ['mp3','wav','m4a','aac','ogg','flac','mp4'], true)) {
                fail('Format non supporté (' . $ext . ').');
            }
            $token = 'up_' . rand_id() . '.' . $ext;
            $dest  = DATA_DIR . '/' . $token;
            if (!move_uploaded_file($f['tmp_name'], $dest)) {
                fail('Échec de l\'enregistrement du fichier.', 500);
            }
            $dur = ff_duration($dest);
            if ($dur <= 0) {
                @unlink($dest);
                fail('Fichier audio illisible.');
            }
            json_out(['ok' => true, 'token' => $token, 'name' => $f['name'], 'duration' => $dur]);
        }

        /* ----- Téléchargement YouTube ----- */
        case 'youtube': {
            $url = trim((string) ($_POST['url'] ?? ''));
            json_out(['ok' => true] + youtube_download($url));
        }

        /* ----- Génération du message final (TTS + mixage) ----- */
        case 'generate': {
            $c       = cfg_load();
            $voiceId = (string) ($_POST['voice_id'] ?? '');
            $text    = trim((string) ($_POST['text'] ?? ''));
            if ($text === '') {
                fail('Le texte du message est vide.');
            }
            $settings = [
                'stability'     => $_POST['stability']     ?? $c['stability'],
                'similarity'    => $_POST['similarity']    ?? $c['similarity'],
                'style'         => $_POST['style']         ?? $c['style'],
                'speaker_boost' => isset($_POST['speaker_boost']) ? ($_POST['speaker_boost'] !== 'false') : $c['speaker_boost'],
            ];

            // 1) TTS (avec cache : musique modifiée seule = pas de nouvelle facturation)
            $tts       = el_tts_file($voiceId, $text, $settings, $c['model_id']);
            $voicePath = $tts['path'];

            // 2) Musique éventuelle
            $musicPath = null;
            $token = (string) ($_POST['music_token'] ?? '');
            if ($token !== '') {
                $musicPath = DATA_DIR . '/' . safe_token($token);
                if (!is_file($musicPath)) {
                    fail('Musique introuvable, ré-importe-la.');
                }
            }

            // 3) Mixage → WAV 8kHz
            $opt = [
                'intro'        => $_POST['intro']        ?? $c['intro'],
                'tail'         => $_POST['tail']         ?? $c['tail'],
                'music_volume' => $_POST['music_volume'] ?? $c['music_volume'],
                'ducking'      => isset($_POST['ducking']) ? ($_POST['ducking'] !== 'false') : $c['ducking'],
            ];
            $res = mix_message($voicePath, $musicPath, $opt);
            // $voicePath est en cache : on ne le supprime pas (réutilisable gratuitement).

            json_out([
                'ok'       => true,
                'file'     => $res['file'],
                'url'      => 'output/' . $res['file'],
                'duration' => $res['duration'],
                'cached'   => $tts['cached'],
            ]);
        }

        default:
            fail('Action inconnue.', 404);
    }
} catch (Throwable $e) {
    fail('Erreur serveur : ' . $e->getMessage(), 500);
}
