#!/usr/bin/env python3
# app.py

import asyncio
import sys
import signal
from dataclasses import dataclass, field
from typing import List

import speech_recognition as sr
from gtts import gTTS
from pytgcalls import PyTgCalls, idle
from pytgcalls.types import MediaStream, Update
from pytgcalls import filters as call_filters
from pyrogram import Client

# Assuming Corcel is correctly imported and configured
from corcel import Corcel

@dataclass
class Config:
    device_index: int = 6  # Microphone device index
    phrase_time_limit: int = 4
    recognition_language: str = 'id-ID'
    tts_language: str = 'id'
    audio_output_file: str = 'input.mp3'
    telegram_chat_id: str = '-1001218880477'
    account_credentials: dict = field(default_factory=lambda: {
        "s3rverdenied": {
            "name": "acc",
            "api_id": 26096884,
            "api_hash": "0a17b16cfe5e7f0297f4f0eca155b92d",
            "phone_number": "+6281818475959",
            "session_string": "BQGONPQANJQm-VG6XVT-GoK3DAeIyAbmC0q-t5CvHTuFo_AOFjF9zHoJ6M2cYdKkE0lFXLHLLXltyTCVwQA-KfMCgpjcGB8JVT2FoxCgIsoYUnOhXP9i2vNZFD8_DY4c4mZq2SPCr3ymI_nTf7Q-vvMe-lbNVSy6WWZtvoe8HhR8p5z9ZUXKZRH-bO3dSaj49FcAjKTlKBVKEUCBksG-cZp4H3dniUwf-bU1lHWV7dPgUAShr4If37A3IdCem0t0wNMlvvzDA_2N0sGFM_irAWM_4H8Lkv-_-5hY-gpUXObRwnJo695wEOZHqJbJgclhDBJ1-F4e9C2vkrQFSQlw9N50KF-7tgAAAAAiSSfLAA"
        }
    })


@dataclass
class VoiceRecognizer:
    config: Config
    recognizer: sr.Recognizer = field(default_factory=sr.Recognizer)
    provider: Corcel = field(default_factory=Corcel)
    queue: asyncio.Queue = field(default_factory=asyncio.Queue)
    text_results: str = ''
    can_listen: asyncio.Event = field(default_factory=lambda: asyncio.Event())

    def __post_init__(self):
        # Initially, allow listening
        self.can_listen.set()

    async def detect_voice(self):
        device_index = self.config.device_index

        with sr.Microphone(device_index=device_index) as source:
            print("Adjusting for ambient noise... Please wait.")
            self.recognizer.adjust_for_ambient_noise(source)
            print("Ready. Please speak.")

            while True:
                # Wait until listening is allowed
                await self.can_listen.wait()

                try:
                    print("Listening for audio input...")
                    audio = await asyncio.to_thread(
                        self.recognizer.listen, source, phrase_time_limit=self.config.phrase_time_limit
                    )

                    r_text_results = await asyncio.to_thread(
                        self.recognizer.recognize_google, audio, language=self.config.recognition_language
                    )
                    print(f"Recognized Text: {r_text_results}")

                    # Assuming Corcel.chat is an I/O-bound synchronous function
                    self.text_results = await asyncio.to_thread(
                        self.provider.chat, f"{r_text_results}\njawab dengan singkat!", history=[]
                    )

                    await self.queue.put(1)

                except sr.UnknownValueError:
                    print("Could not understand audio")
                except sr.RequestError as e:
                    print(f"Could not request results; {e}")
                except Exception as e:
                    print(f"Unexpected error: {e}")

    async def process_queue(self, app, client: PyTgCalls):
        while True:
            await self.queue.get()
            # Pause listening while processing
            self.can_listen.clear()
            print("Processing Text Results")
            print(self.text_results)

            try:
                tts = gTTS(self.text_results, lang=self.config.tts_language)
                tts.save(self.config.audio_output_file)
                print("TTS audio generated.")

                await client.play(
                    self.config.telegram_chat_id,
                    MediaStream(self.config.audio_output_file)
                )
                print("Audio played successfully.")

                self.text_results = ""
            except Exception as e:
                print(f"Error during TTS or playing media: {e}")
            finally:
                # Resume listening after processing
                self.can_listen.set()

            self.queue.task_done()


@dataclass
class TelegramBot:
    config: Config
    client: Client = field(init=False)
    pytg_calls: PyTgCalls = field(init=False)

    def __post_init__(self):
        account = self.config.account_credentials["s3rverdenied"]
        self.client = Client(**account)
        self.pytg_calls = PyTgCalls(self.client)

    async def start(self, recognizer: VoiceRecognizer):
        await self.pytg_calls.start()
        print("Telegram PyTgCalls started.")

        loop = asyncio.get_event_loop()
        # Start voice detection and queue processing
        asyncio.create_task(recognizer.detect_voice())
        asyncio.create_task(recognizer.process_queue(self, self.pytg_calls))
        await idle()

    async def stop(self):
        await self.pytg_calls.stop()
        await self.client.stop()
        print("Telegram PyTgCalls stopped.")


async def main():
    config = Config()
    recognizer = VoiceRecognizer(config)
    bot = TelegramBot(config)

    # Handle graceful shutdown
    loop = asyncio.get_running_loop()
    shutdown_event = asyncio.Event()

    def on_shutdown():
        print("Shutdown signal received.")
        shutdown_event.set()

    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, on_shutdown)

    # Start the bot
    asyncio.create_task(bot.start(recognizer))

    # Wait for shutdown signal
    await shutdown_event.wait()

    # Stop the bot gracefully
    await bot.stop()
    print("Bot has been stopped gracefully.")


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except Exception as e:
        print(f"An error occurred: {e}")


#PERINTAH
 print("Listening for audio input...")
                    audio = await asyncio.to_thread(
                        self.recognizer.listen, source, phrase_time_limit=self.config.phrase_time_limit
                    )

KALO ADA QUEUE GK BAKALAN LISTENING DIA SAMPE PROSESNYA QUEUENYA SELESAI