from typing import Any, Dict

from langchain.chains.base import Chain
from langchain.agents import Tool
from langchain_core.language_models.chat_models import BaseChatModel

from chain import CasinoChainCreator, FinanceChainCreator, GameChainCreator, AffiliateChainCreator, MarketingChainCreator
from qwin_bot_domain import QwinBotConversationContext

class QwinBotToolsCreator:
    def __init__(self, llm: BaseChatModel, initial_params: Dict[str, Any]):
        self.llm = llm
        self.initial_params = initial_params
        
        self.affiliate_chain_creator = AffiliateChainCreator(llm)
        self.casino_chain_creator = CasinoChainCreator(llm)
        self.game_chain_creator = GameChainCreator(llm, initial_params)
        self.finance_chain_creator = FinanceChainCreator(llm)
        self.marketing_chain_creator = MarketingChainCreator(llm)
        

    def qwin_bot_tools(self, 
                       user_id: str,
                       conv_context: QwinBotConversationContext) -> [Tool]:
        return [
            Tool(
                name='Casinoassistant',
                func=invoke_chain(self.casino_chain_creator.casino_chain(user_id), conv_context),
                description='''Useful when you need to answer questions 
                about the operation of QWIN online casino, 
                casino rules, casino restrictions, user registration, user account.
                Don not use it for questions about games.
                '''),
                
            Tool(
                name='Financeassistant',
                func=invoke_chain(self.finance_chain_creator.finance_chain(user_id), conv_context),
                description='''Useful when you need to answer questions 
                about the money transferring in QWin online casino, 
                deposits, withdrawals QWin online casino, casino currencies and financial queries.
                '''),
                
            Tool(
                name='Marketingassistant',
                func=invoke_chain(self.marketing_chain_creator.marketing_chain(user_id), conv_context),
                description='''Useful when you need to answer questions 
                about the marketing events and features in QWIN online casino, 
                bonuses, user loyalty.
                '''),
                
            Tool(
                name='Affiliateassistant',
                func=invoke_chain(self.affiliate_chain_creator.affiliate_chain(user_id), conv_context),
                description='''Useful when you need to answer questions 
                about the affiliate program for QWIN online casino, 
                promo links, affiliate users, affiliate payments and benefits.
                '''),
                
            Tool(
                name='Gamesassistant',
                func=invoke_chain(self.game_chain_creator.games_chain(user_id), conv_context),
                description='''Useful when you need to answer questions 
                about games, QWIN online casino games, games list, card games, slot games, 
                videopokers, roulettes, game rules, winnings and search games by any feature (eg: symbol, slot theme, specific feature win).
                Useful for questions about game outcomes, explanations of game situations
                DO NOT transform human's input.'
                '''),
            Tool(
                name='Operatorsassistant',
                func=lambda x: 'Recommend to contact the support service by email support@qwin.io.',
                description='''Useful when user asks or needs help of operator. 
                ''')
        ]
                
def invoke_chain(chain: Chain, 
                 conv_context: QwinBotConversationContext, 
                 **kwargs: Any):
    def _invoke_chain(input_str: str, **kwargs: Any):
        return chain.invoke({'input': input_str, 'chat_history': list(conv_context.chat_history)}, kwargs)
        
    return _invoke_chain