import os
import subprocess
import sys
from functools import lru_cache

from rvc.lib.tools.prerequisites_download import prequisites_download_pipeline
from tts_service.utils import cache_path
from tts_service.voices import voice_manager

python = sys.executable


@lru_cache(maxsize=None)
def import_voice_converter():
    from rvc.infer.infer import VoiceConverter

    return VoiceConverter()


# TTS
def run_tts_script(
    tts_text: str,
    voice_name: str,
    tts_rate: int,
) -> tuple[str, str]:
    tts_script_path = os.path.join("rvc", "lib", "tools", "tts.py")

    voice = voice_manager.voices[voice_name]
    format = "wav"

    output_tts_path = cache_path(voice.tts, "", tts_rate, tts_text, extension=format)
    if not os.path.exists(output_tts_path):
        command_tts = [
            *map(
                str,
                [
                    python,
                    tts_script_path,
                    "",  # tts_file
                    tts_text,
                    voice.tts,
                    tts_rate,
                    output_tts_path,
                ],
            ),
        ]
        subprocess.run(command_tts)

    output_rvc_path = cache_path(voice.tts, voice.name, tts_rate, tts_text, extension=format)
    if not os.path.exists(output_rvc_path):
        infer_pipeline = import_voice_converter()
        infer_pipeline.convert_audio(
            pitch=voice.pitch,
            filter_radius=voice.filter_radius,
            index_rate=voice.index_rate,
            volume_envelope=voice.rms_mix_rate,
            protect=voice.protect,
            hop_length=voice.hop_length,
            f0_method=voice.f0_method,
            audio_input_path=str(output_tts_path),
            audio_output_path=str(output_rvc_path),
            model_path=voice.model,
            index_path=voice.index,
            split_audio=False,
            f0_autotune=voice.autotune is not None,
            f0_autotune_strength=voice.autotune,
            clean_audio=voice.clean is not None,
            clean_strength=voice.clean,
            export_format=format.upper(),
            upscale_audio=voice.upscale,
            f0_file=None,
            embedder_model=voice.embedder_model,
            embedder_model_custom=None,
            sid=0,
            formant_shifting=None,
            formant_qfrency=None,
            formant_timbre=None,
            post_process=None,
            reverb=None,
            pitch_shift=None,
            limiter=None,
            gain=None,
            distortion=None,
            chorus=None,
            bitcrush=None,
            clipping=None,
            compressor=None,
            delay=None,
            sliders=None,
        )

    return "Text synthesized successfully.", str(output_rvc_path)


# Prerequisites
def run_prerequisites_script(
    pretraineds_v1_f0: bool,
    pretraineds_v1_nof0: bool,
    pretraineds_v2_f0: bool,
    pretraineds_v2_nof0: bool,
    models: bool,
    voices: bool,
):
    prequisites_download_pipeline(
        pretraineds_v1_f0,
        pretraineds_v1_nof0,
        pretraineds_v2_f0,
        pretraineds_v2_nof0,
        models,
        voices,
    )
    return "Prerequisites installed successfully."