import os
import ffmpeg
import hashlib
from typing import Tuple
from werkzeug.datastructures import FileStorage


class FileHandler:
    
    def convert_to_wav(input_path: str, output_path: str) -> str:
        # Define the input stream
        input_stream = ffmpeg.input(input_path) 
        # Check if the output file already exists
        overwrite_output = '-y' if os.path.exists(output_path) else None  
        # Define the output stream with the overwrite_output option
        output_stream = ffmpeg.output(input_stream, output_path, acodec='pcm_s16le', ar=44100, ac=2, y=overwrite_output) 
        # Run the command
        ffmpeg.run(output_stream, overwrite_output=True) 
        # Print the conversion message
        print(f"File converted to WAV: {output_path}") 
        # Return the output path
        return output_path

    def get_file_extension(file_storage) -> str:
        """
        Get the file extension from a FileStorage object.

        :param file_storage: The FileStorage object.
        :return: The file extension (including the dot), or None if not found.
        """
        if not isinstance(file_storage, FileStorage):
            raise ValueError("Invalid argument: 'file_storage' must be a FileStorage object.")

        filename = file_storage.filename
        if '.' in filename:
            return '.' + filename.rsplit('.', 1)[1].lower()
        else:
            return None
    
    @staticmethod
    def save_file(file_storage, upload_dir: str, chunk_size: int = 1024 * 1024) -> Tuple[str, str]:
        """
        Save the uploaded file with chunked upload and calculate the file's SHA-256 hash.

        :param file_storage: The FileStorage object containing the uploaded file.
        :param upload_dir: The directory where the file will be saved.
        :param chunk_size: The size of each chunk in bytes. Defaults to 1 MB.
        :return: A tuple containing the path to the saved file and the file's SHA-256 hash.
        """
        filename = file_storage.filename
        extention = FileHandler.get_file_extension(file_storage)
        import uuid
        upload_dir = os.path.join(upload_dir, 'videos') if file_storage.content_type.startswith('video') else os.path.join(upload_dir, 'audios') if file_storage.content_type.startswith('audio') else upload_dir
        # Generate & Transform UUID to hexadecimal
        file_name = (uuid.uuid4()).hex
        file_path = os.path.join(upload_dir, f"{file_name}{extention}")
        sha256 = hashlib.sha256()

        try:
            with open(file_path, 'wb') as f:
                while True:
                    chunk = file_storage.stream.read(chunk_size)
                    if not chunk:
                        break
                    f.write(chunk)
                    sha256.update(chunk)

            file_hash = sha256.hexdigest()
            return file_path, file_hash

        except Exception as e:
            print(f"Error saving file: {e}")
            return None, None
