import apiClient from './apiClient.js'; import { formatCurrency, formatPercent } from './uiUtils.js'; class AIAdvisorView { constructor(section) { this.section = section; this.form = section?.querySelector('[data-ai-form]'); this.decisionContainer = section?.querySelector('[data-ai-result]'); this.sentimentContainer = section?.querySelector('[data-sentiment-result]'); this.disclaimer = section?.querySelector('[data-ai-disclaimer]'); this.contextInput = section?.querySelector('textarea[name="context"]'); this.modelSelect = section?.querySelector('select[name="model"]'); } init() { if (!this.form) return; this.form.addEventListener('submit', async (event) => { event.preventDefault(); const formData = new FormData(this.form); await this.handleSubmit(formData); }); } async handleSubmit(formData) { const symbol = formData.get('symbol') || 'BTC'; const horizon = formData.get('horizon') || 'swing'; const risk = formData.get('risk') || 'moderate'; const context = (formData.get('context') || '').trim(); const mode = formData.get('model') || 'auto'; if (this.decisionContainer) { this.decisionContainer.innerHTML = '

Generating AI strategy...

'; } if (this.sentimentContainer && context) { this.sentimentContainer.innerHTML = '

Running sentiment model...

'; } const decisionPayload = { query: `Provide ${horizon} outlook for ${symbol} with ${risk} risk. ${context}`, symbol, task: 'decision', options: { horizon, risk }, }; const jobs = [apiClient.runQuery(decisionPayload)]; if (context) { jobs.push(apiClient.analyzeSentiment({ text: context, mode })); } const [decisionResult, sentimentResult] = await Promise.all(jobs); if (!decisionResult.ok) { this.decisionContainer.innerHTML = `
${decisionResult.error}
`; } else { this.renderDecisionResult(decisionResult.data || {}); } if (context && this.sentimentContainer) { if (!sentimentResult?.ok) { this.sentimentContainer.innerHTML = `
${sentimentResult?.error || 'AI sentiment endpoint unavailable'}
`; } else { this.renderSentimentResult(sentimentResult.data || sentimentResult); } } } renderDecisionResult(response) { if (!this.decisionContainer) return; const payload = response.data || {}; const analysis = payload.analysis || payload; const summary = analysis.summary?.summary || analysis.summary || 'No summary provided.'; const signals = analysis.signals || {}; const topCoins = (payload.top_coins || []).slice(0, 3); this.decisionContainer.innerHTML = `

${response.message || 'Decision support summary'}

${summary}

Market Signals

    ${Object.entries(signals) .map(([, value]) => `
  • ${value?.label || 'neutral'} (${value?.score ?? '—'})
  • `) .join('') || '
  • No model signals.
  • '}

Watchlist

    ${topCoins .map( (coin) => `
  • ${coin.symbol || coin.ticker}: ${formatCurrency(coin.price)} (${formatPercent(coin.change_24h)})
  • `, ) .join('') || '
  • No coin highlights.
  • '}
`; if (this.disclaimer) { this.disclaimer.textContent = response.data?.disclaimer || 'This AI output is experimental research and not financial advice.'; } } renderSentimentResult(result) { const container = this.sentimentContainer; if (!container) return; const payload = result.result || result; const signals = result.signals || payload.signals || {}; container.innerHTML = `

Sentiment (${result.mode || 'auto'})

Label: ${payload.label || payload.classification || 'neutral'}

Score: ${payload.score ?? payload.sentiment?.score ?? '—'}

${Object.entries(signals) .map(([key, value]) => `${key}: ${value?.label || 'n/a'}`) .join('') || ''}

${payload.summary?.summary || payload.summary?.summary_text || payload.summary || ''}

`; } } export default AIAdvisorView;