/**
 * Dynamic Claude Model Manager
 * Provides up-to-date Claude model options with fallback to static list
 */

export interface ClaudeModel {
	name: string;
	value: string;
	description?: string;
	isRecommended?: boolean;
}

export interface ModelManagerConfig {
	includeDeprecated?: boolean;
	includeExperimental?: boolean;
	cacheDuration?: number; // in minutes
}

export class ModelManager {
	private static instance: ModelManager;
	private cachedModels: ClaudeModel[] | null = null;
	private lastFetch: Date | null = null;
	private readonly cacheDuration: number;

	// Claude Code available models - simplified list
	private readonly knownModels: ClaudeModel[] = [
		{
			name: 'Sonnet (Latest)',
			value: 'sonnet',
			description: 'Latest Sonnet model',
			isRecommended: true,
		},
		{
			name: 'Opus (Latest)',
			value: 'opus',
			description: 'Latest Opus model',
			isRecommended: true,
		},
	];

	private readonly legacyModels: ClaudeModel[] = [];

	private constructor(config: ModelManagerConfig = {}) {
		this.cacheDuration = config.cacheDuration || 60; // 1 hour default
	}

	public static getInstance(config?: ModelManagerConfig): ModelManager {
		if (!ModelManager.instance) {
			ModelManager.instance = new ModelManager(config);
		}
		return ModelManager.instance;
	}

	/**
	 * Get all available Claude models
	 */
	public async getAvailableModels(config: ModelManagerConfig = {}): Promise<ClaudeModel[]> {
		// Check cache first
		if (this.isCacheValid()) {
			return this.cachedModels!;
		}

		try {
			// Try to fetch latest models (placeholder for future API integration)
			const models = await this.fetchLatestModels(config);
			this.cachedModels = models;
			this.lastFetch = new Date();
			return models;
		} catch (error) {
			console.warn('Failed to fetch latest models, using known models:', error.message);
			// Fallback to known models
			return this.getKnownModels(config);
		}
	}

	/**
	 * Get models for n8n node options format
	 */
	public async getModelOptions(config: ModelManagerConfig = {}): Promise<Array<{ name: string; value: string }>> {
		const models = await this.getAvailableModels(config);
		return models.map(model => ({
			name: model.name,
			value: model.value,
		}));
	}

	/**
	 * Validate if a model is available
	 */
	public async isValidModel(modelValue: string): Promise<boolean> {
		const models = await this.getAvailableModels();
		return models.some(model => model.value === modelValue);
	}

	/**
	 * Get recommended model
	 */
	public async getRecommendedModel(): Promise<ClaudeModel> {
		const models = await this.getAvailableModels();
		const recommended = models.find(model => model.isRecommended);
		return recommended || models[0]; // Fallback to first model
	}

	/**
	 * Get model by value
	 */
	public async getModelByValue(value: string): Promise<ClaudeModel | null> {
		const models = await this.getAvailableModels();
		return models.find(model => model.value === value) || null;
	}

	private isCacheValid(): boolean {
		if (!this.cachedModels || !this.lastFetch) {
			return false;
		}
		const now = new Date();
		const diffInMinutes = (now.getTime() - this.lastFetch.getTime()) / (1000 * 60);
		return diffInMinutes < this.cacheDuration;
	}

	private async fetchLatestModels(config: ModelManagerConfig): Promise<ClaudeModel[]> {
		// Future implementation: Could fetch from Anthropic API or configuration service
		// For now, simulate API call and return known models
		await new Promise(resolve => setTimeout(resolve, 100)); // Simulate network call
		
		// This would be replaced with actual API call in the future
		return this.getKnownModels(config);
	}

	private getKnownModels(config: ModelManagerConfig = {}): ClaudeModel[] {
		let models = [...this.knownModels];

		// Add legacy models if requested
		if (config.includeDeprecated !== false) {
			models = [...models, ...this.legacyModels];
		}

		// Sort by recommendation and then by name
		models.sort((a, b) => {
			if (a.isRecommended && !b.isRecommended) return -1;
			if (!a.isRecommended && b.isRecommended) return 1;
			return a.name.localeCompare(b.name);
		});

		return models;
	}

	/**
	 * Clear cache and force refresh on next request
	 */
	public clearCache(): void {
		this.cachedModels = null;
		this.lastFetch = null;
	}

	/**
	 * Get Claude Command Options string for the given model
	 */
	public getClaudeCommandOptions(model: string): string {
		// Map model values to Claude CLI options
		const modelMappings: Record<string, string> = {
			'sonnet': '--model sonnet',
			'opus': '--model opus',
		};

		return modelMappings[model] || `--model ${model}`;
	}
}

// Export singleton instance
export const modelManager = ModelManager.getInstance();