import os
import json
import logging
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional
# Gemini用のライブラリ (標準はgoogle-genaiを想定)
from google import genai
from google.genai import types

logger = logging.getLogger(__name__)

class AICommentGenerator(ABC):
    """
    AIを利用したコメント生成機能の抽象基底クラス。
    将来的にGemini以外（OpenAI, Claudeなど）を用いる際の拡張性を持たせる。
    """
    @abstractmethod
    def generate_reply(self, tweet_text: str, user_profile: str, prompt_template: str) -> str:
        """
        ツイート本文、プロフィール、システムプロンプトを受け取り、
        AIにリプライ文案を生成させる抽象メソッド。
        """
        pass


class GeminiCommentGenerator(AICommentGenerator):
    """
    Google Gemini API を利用したコメント生成クラス。
    """
    def __init__(self, settings: Dict[str, Any] = None):
        """
        スプレッドシートの設定値（settings）から Gemini API キーを取得し、
        クライアントを初期化する。
        """
        self.api_key = None
        if settings and "gemini_api_key" in settings:
            self.api_key = str(settings["gemini_api_key"]).strip()

        # 互換性フォールバック（もし設定されていなかったら念のため環境変数も探す）
        if not self.api_key:
            self.api_key = os.environ.get("GEMINI_API_KEY")

        if not self.api_key:
            raise ValueError("エラー: スプレッドシートの変数名 'gemini_api_key' にAI APIキーが入力されていません。")

        try:
             # google-genai クライアントの初期化。APIキーを明示的に渡す
            self.client = genai.Client(api_key=self.api_key)
            self.model_name = "gemini-2.5-flash"  # コスト・速度バランスの良いモデル
            logger.info(f"Gemini クライアントを初期化しました。使用モデル: {self.model_name}")
        except Exception as e:
            logger.error(f"Gemini クライアントの初期化に失敗しました。環境変数 GEMINI_API_KEY が設定されているか確認してください: {e}")
            raise

    def generate_reply(self, tweet_text: str, user_profile: str, prompt_template: str) -> str:
        """Gemini API を呼び出してツイートに対するリプライ案を生成する（429時は自動リトライ）"""
        import time

        if not prompt_template:
            prompt_template = "以下のツイートに対し共感を示し、短く優しいメッセージを返してください。"

        context = f"""
{prompt_template}

【ターゲット情報】
プロフィール: {user_profile if user_profile else "(プロフィール情報なし)"}
ツイート本文: {tweet_text}

【出力ルール】
- 100文字以内で作成すること。
- ハッシュタグは使用しないこと。
- そのままツイート（リプライ）できる形式のテキストのみを出力し、挨拶文や解説などの余計な文字列は含めないこと。
"""

        max_retries = 3
        wait_seconds = 20  # 初回待機（429対策）

        for attempt in range(1, max_retries + 1):
            try:
                response = self.client.models.generate_content(
                    model=self.model_name,
                    contents=context,
                    config=types.GenerateContentConfig(
                        temperature=0.7,
                    )
                )
                result_text = response.text.strip() if response.text else ""
                logger.info("AIのコメント生成に成功しました。")
                return result_text

            except Exception as e:
                err_str = str(e)
                if "429" in err_str or "RESOURCE_EXHAUSTED" in err_str:
                    if attempt < max_retries:
                        logger.warning(f"Gemini 429 レート制限エラー。{wait_seconds}秒後にリトライします（{attempt}/{max_retries}）...")
                        time.sleep(wait_seconds)
                        wait_seconds *= 2  # バックオフ（20→40秒）
                    else:
                        logger.error(f"Gemini 429 エラー: リトライ上限に達しました。スキップします。")
                else:
                    logger.error(f"AIコメントの生成中にエラーが発生しました: {e}")
                    break  # 429以外は即座にあきらめる

        return "[AIエラー: 手動で作成してください]"

# 今後の拡張用 (ChatGPT)
class OpenAICommentGenerator(AICommentGenerator):
    def __init__(self):
        # ... 初期化処理 ...
        pass
        
    def generate_reply(self, tweet_text: str, user_profile: str, prompt_template: str) -> str:
        # ... OpenAI API 呼び出し処理 ...
        return "OpenAI版の実装は準備中です"

# ファクトリークラス
class CommentGeneratorFactory:
    """設定に応じて使用するAIモデルのクラスを生成・返却するファクトリー"""
    @staticmethod
    def get_generator(ai_type: str = "gemini", settings: Dict[str, Any] = None) -> AICommentGenerator:
        if ai_type.lower() == "gemini":
            return GeminiCommentGenerator(settings)
        elif ai_type.lower() == "openai":
            return OpenAICommentGenerator()
        else:
            logger.warning(f"未知のAIタイプ '{ai_type}' が指定されました。デフォルトのGeminiを使用します。")
            return GeminiCommentGenerator(settings)


if __name__ == "__main__":
    # テスト用
    logging.basicConfig(level=logging.INFO)
    try:
        # 環境変数が設定されていない場合のエラー回避策（テスト用）
        if not os.environ.get("GEMINI_API_KEY"):
            print("警告: テスト実行には環境変数 GEMINI_API_KEY が必要です。")
        else:
            generator = CommentGeneratorFactory.get_generator("gemini")
            reply = generator.generate_reply(
                tweet_text="今日も仕事でミスして怒られた…。もう限界かも。",
                user_profile="しがない会社員。毎日つらい。HSP気味。",
                prompt_template="あなたは発達障害やHSP向けの自助会の主催者です。まず相手の感情に共感し、自助会をやっていることを優しく伝えてください。"
            )
            print("\n【生成されたリプライ案】")
            print(reply)
            
    except Exception as e:
        print(f"Test failed: {e}")
