import os
import traceback
import uuid
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Optional

from flask import Flask, Response, jsonify, request
from flask_httpauth import HTTPTokenAuth

from sziszapangma.integration.base_asr_service.asr_result import AsrResult

_TEMP_DIRECTORY = "asr_processing"
_AUTH_TOKEN = "AUTH_TOKEN"
_SERVICE_PORT = "SERVICE_PORT"


class AsrProcessor(ABC):
    user_token: str

    def __init__(self):
        self.user_token = os.environ[_AUTH_TOKEN]

    @abstractmethod
    def process_asr(self, audio_file_path: str) -> AsrResult:
        """Method to call for ASR results."""

    def process_request(self) -> Response:
        file_tag = str(uuid.uuid4())
        f = request.files["file"]
        if f is not None and f.filename is not None:
            file_extension = f.filename.split(".")[-1]
            file_name = f"{file_tag}.{file_extension}"
            file_path = f"{_TEMP_DIRECTORY}/{file_name}"
            f.save(file_path)
            try:
                transcription = self.process_asr(file_path)
                os.remove(file_path)
                result_object = jsonify(
                    {"transcription": transcription.words, "full_text": transcription.full_text}
                )
            except Exception as exception:
                print(exception)
                traceback.print_exc()
                result_object = jsonify({"error": "Error on asr processing"})
        else:
            result_object = jsonify({"error": "Error on asr processing"})
        return result_object

    def is_token_correct(self, token: str) -> Optional[str]:
        if token == self.user_token:
            return "asr_client"
        else:
            return None

    def health_check(self) -> Response:
        return jsonify({"status": "running"})

    def start_processor(self):
        app = Flask(__name__)
        auth = HTTPTokenAuth(scheme="Bearer")
        auth.verify_token(self.is_token_correct)
        Path(_TEMP_DIRECTORY).mkdir(parents=True, exist_ok=True)
        app.route("/process_asr", methods=["POST"])(auth.login_required(self.process_request))
        app.route("/health_check", methods=["GET"])(self.health_check)
        port = int(os.environ[_SERVICE_PORT]) if _SERVICE_PORT in os.environ else 5000
        app.run(debug=True, host="0.0.0.0", port=port)