'use strict';

const conf = require('../conf');
const {sleep} = require('../utils');
const { ProviderFactory } = require('./ai/providers');


class Ai{
	constructor(args){
		this.bot = args.bot;
		this.promptName = args.promptName;
		this.prompCustom = args.prompCustom || '';
		// interval takes precedence over intervalLength (both are valid config names)
		this.intervalLength = args.interval || args.intervalLength || 30;
		this.intervalStop;
		this.messageListener;
		this.provider = null;

		// Bot-specific AI config (overrides global config)
		// When loaded via config, args contains provider, model, baseUrl, etc. directly
		// When loaded via /ai command, only promptName/prompCustom are passed
		const { bot, promptName, prompCustom, intervalLength, interval, ...configProps } = args;
		this.botConfig = args.botConfig || configProps || {};
	}

	// Get merged config: bot-specific settings override global settings
	__getConfig() {
		return {
			...conf.ai,  // Global defaults
			...this.botConfig,  // Bot-specific overrides
		};
	}

	async init(){
		this.bot.on('onReady', async (argument)=>{
			try{
				await this.start();
				let messages = [''];

				this.messageListener = this.bot.on('message', (message, type)=>{
					if(type === 'game_info') return;
					if(message.toString().startsWith('<') && message.toString().split('>')[0].includes(this.bot.bot.entity.username)){
						console.log('message blocked from message array')
						return;
					}
					console.log(`Message ${type}: ${message.toString()}`)
					messages.push('>', message.toString());
				});

				this.intervalStop = setInterval(async ()=>{
					let result;

					try{
						result = await this.chat(JSON.stringify({
							messages, currentTime:Date.now()+1}
						));
					}catch(error){
						console.log('error AI API', error, result);
						messages = [];
						return ;
					}

					try{
						messages = [''];
						const responseText = this.provider.getResponse(result);
						if(!responseText) return;

						// Try to parse JSON response
						try {
							const parsed = JSON.parse(responseText);
							if(Array.isArray(parsed)){
								for(let message of parsed){
									console.log('toSay', message.delay, message.text);
									if(message.text.trim().startsWith('_')) return;
									setTimeout(async (message)=>{
										await this.bot.sayAiSafe(message.text);
									}, 0*1000, message);
								}
							} else {
								throw new Error('Response is not an array');
							}
						} catch(jsonError){
							// JSON parsing failed, treat as plain text
							console.log('JSON parse failed, treating as plain text:', responseText.substring(0, 100));
							// Skip empty responses, underscore signals, and single dash signals
							const text = responseText.trim();
							if(text && text !== '___' && !text.match(/^[-_]+$/)){
								await this.bot.sayAiSafe(text);
							}
						}
					}catch(error){
						console.log('Error in AI message loop', error, result);
						try {
							if(result && this.provider.getResponse(result)){
								console.log(this.provider.getResponse(result))
							}
						} catch(e) {
							// Ignore
						}
					}
				}, this.intervalLength*1000);

			}catch(error){
				console.log('error in onReady', error);
			}
		});
	}

	async unload(){
		if(this.intervalStop){
			clearInterval(this.intervalStop);
			this.intervalStop = undefined;
		}
		if(this.messageListener){
			this.messageListener();
		}
		if(this.provider){
			await this.provider.close();
		}
		return true;
	}

	async start(history){
		const config = this.__getConfig();
		let bulbaItems = {};

		console.log(`${this.bot.name} AI config:`, {
			provider: config.provider,
			model: config.model,
			promptName: this.promptName,
			baseUrl: config.baseUrl,
			maxOutputTokens: config.maxOutputTokens,
			interval: config.interval,
		});

		const prompt = conf.ai.prompts[this.promptName](
			this.bot.bot.entity.username,
			config.interval,
			Object.values(this.bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n'),
			bulbaItems,
			this.prompCustom,
		);

		// Create the provider instance with merged config and prompt
		this.provider = ProviderFactory.create({
			...config,
			prompt: prompt,
		});

		await this.provider.start(history);
		console.log(`${this.bot.name} AI ${config.provider} provider started (model: ${config.model})`);
	}

	async chat(message, retryCount=0){
		console.log(`chat ${this.bot.name}`, retryCount)
		try{
			let result = await this.provider.chat(message);
			return result
		}catch(error){
			console.log('AI chat error', error)
			throw error;
		}
	}
}



const AiWeb = require('./ai/web');
Ai.createRouter = AiWeb.createRouter;
Ai.webUI = AiWeb.webUI;

module.exports = Ai;