import threading
import time
from typing import Dict, Any, Optional
import requests
import json

from pilot.generater.generation_config import GenerationConfigDTO


class MattermostAISingleton:
    _instance: Optional['MattermostAISingleton'] = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super(MattermostAISingleton, cls).__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self,
                 model_name: str = "gpt-4",
                 api_key: str = "123456",
                 base_url: str = "http://127.0.0.1:8080"):

        if not self._initialized:
            with self._lock:
                if not self._initialized:
                    self.model_name = model_name
                    self.api_key = api_key
                    # 疎通コードに合わせベースURLを保持
                    self.base_url = base_url.rstrip('/')

                    self._session = requests.Session()
                    # 疎通OK版のヘッダー構成を完全に再現
                    self._session.headers.update({
                        "Authorization": f"Bearer {self.api_key}",
                        "Content-Type": "application/json"
                    })

                    self._initialized = True

    def generate_content(
            self,
            prompt: str,
            gen_config: Optional[GenerationConfigDTO] = None,
            stream: Optional[bool] = None,
            **kwargs
    ) -> Dict[str, Any]:
        """単発呼び出しモード"""
        try:
            if gen_config is None:
                gen_config = GenerationConfigDTO()

            # メッセージの組み立て (システム命令があれば先頭に追加)
            messages = []
            if gen_config.system_instruction:
                messages.append({"role": "system", "content": gen_config.system_instruction})
            messages.append({"role": "user", "content": prompt})

            # 疎通版の payload 構造をベースに gen_config を反映
            payload = {
                "model": self.model_name,
                "messages": messages,
                "stream": False,
                "temperature": gen_config.temperature if gen_config.temperature is not None else 0.7
            }

            # max_tokens が設定されている場合のみ追加
            if gen_config.max_output_tokens:
                payload["max_tokens"] = gen_config.max_output_tokens

            # 疎通版に合わせ timeout はデフォルト 120。gen_config 指定があれば優先。
            current_timeout = gen_config.timeout if gen_config.timeout else 120

            resp = self._session.post(
                f"{self.base_url}/chat/completions",
                json=payload,
                timeout=current_timeout
            )
            resp.raise_for_status()
            result = resp.json()
            content = result['choices'][0]['message']['content']

            data = json.loads(content)
            json.dumps(data, indent=4, ensure_ascii=False)
            #print(formatted_json)
            #print(result)
            #resultJson = result.json()

            # 疎通版のデータ抽出パス: result['choices'][0]['message']['content']
            content = data['respMessage']

            return {
                "prompt": prompt,
                "response": self._remove_code_fence(content),
                "success": True,
                "error": None
            }

        except Exception as e:
            return {
                "prompt": prompt,
                "response": None,
                "success": False,
                "error": str(e)
            }

    def start_chat(self):
        return _MattermostChatSession(self)

    def count_tokens(self, text: str) -> int:
        return len(text) // 4

    def _remove_code_fence(self, text: str) -> str:
        if not text: return ""
        lines = text.splitlines()
        if lines and lines[0].startswith("```"):
            lines = lines[1:]
        if lines and lines[-1].startswith("```"):
            lines = lines[:-1]
        return "\n".join(lines)

    @classmethod
    def get_instance(cls, **kwargs) -> 'MattermostAISingleton':
        return cls(**kwargs)


class _MattermostChatSession:
    """チャットセッション (継続会話)"""

    def __init__(self, client: MattermostAISingleton):
        self._client = client
        self._messages = []

    def send_message(self, message: str, gen_config: Optional[GenerationConfigDTO] = None):
        if gen_config is None:
            gen_config = GenerationConfigDTO()

        # システムプロンプト対応
        if not self._messages and gen_config.system_instruction:
            self._messages.append({"role": "system", "content": gen_config.system_instruction})

        self._messages.append({"role": "user", "content": message})

        url = f"{self._client.base_url}/chat/completions"

        payload = {
            "model": self._client.model_name,
            "messages": self._messages,
            "stream": False,  # セッションモードは基本的に同期
            "temperature": gen_config.temperature if gen_config.temperature is not None else 0.7
        }

        if gen_config.max_output_tokens:
            payload["max_tokens"] = gen_config.max_output_tokens

        resp = self._client._session.post(
            url,
            json=payload,
            timeout=gen_config.timeout if gen_config.timeout else 120
        )
        resp.raise_for_status()
        data = resp.json()

        reply = data['choices'][0]['message']['content']
        self._messages.append({"role": "assistant", "content": reply})

        class _Resp:
            def __init__(self, text):
                self.text = text

        return _Resp(self._client._remove_code_fence(reply))