// pages/wiki/chat/index.js
import request from '../../../utils/request';

Page({
  data: {
    messages: [],
    inputValue: '',
    isTyping: false,
    scrollAnchor: '',
    _counter: 0,
    quotaRemaining: -1,
    quotaLimit: 0,
    _pendingPrefill: '',
  },

  onLoad(options) {
    if (options && options.fromHistory === '1') {
      const channel = this.getOpenerEventChannel();
      channel.on('historyData', (data) => {
        const msgs = [
          { id: 'h1', role: 'user', content: data.question },
          { id: 'h2', role: 'ai', content: this._cleanMd(data.answer) },
        ];
        this.setData({ messages: msgs, _counter: 2 }, () => this.scrollToBottom());
      });
    } else if (options && options.prefillQuestion) {
      // Only save the question; actual send waits for quota check in onShow
      this._pendingPrefill = decodeURIComponent(options.prefillQuestion);
      this.setData({ inputValue: this._pendingPrefill });
    }
  },

  onShow() {
    this._fetchQuota();
  },

  _fetchQuota() {
    request.get('/plant/chat/quota').then(res => {
      this.setData({
        quotaRemaining: res.remaining,
        quotaLimit: res.limit,
      });
      // Auto-send prefill question only after quota is confirmed
      if (this._pendingPrefill) {
        const q = this._pendingPrefill;
        this._pendingPrefill = '';
        if (res.remaining > 0) {
          this.onSend();
        } else {
          wx.showToast({ title: '今日问答次数已用完，明天再来吧', icon: 'none', duration: 2500 });
        }
      }
    }).catch(() => {});
  },

  goToHistory() {
    wx.navigateTo({ url: '/pages/wiki/chat/history/index' });
  },

  onQuickAsk(e) {
    const query = e.currentTarget.dataset.q;
    this.setData({ inputValue: query }, () => this.onSend());
  },

  onInput(e) {
    this.setData({ inputValue: e.detail.value });
  },

  onSend() {
    const query = this.data.inputValue.trim();
    if (!query || this.data.isTyping) return;

    // 额度检查
    if (this.data.quotaRemaining === 0) {
      wx.showToast({ title: '今日问答次数已用完，明天再来吧', icon: 'none', duration: 2500 });
      return;
    }

    const uid = 'u' + (++this.data._counter);
    const aid = 'a' + (++this.data._counter);
    const len = this.data.messages.length;

    this.setData({
      [`messages[${len}]`]: { id: uid, role: 'user', content: query },
      [`messages[${len + 1}]`]: { id: aid, role: 'ai', content: '' },
      inputValue: '',
      isTyping: true,
    }, () => {
      this.scrollToBottom();
      this._streamRequest(query, aid);
    });
  },

  _streamRequest(query, aiMsgId) {
    let fullText = '';

    request.stream('/plant/chat/stream', { query }, {
      onChunk: (res) => {
        const text = this._decode(res.chunk || res.data);

        // Detect non-SSE JSON error (e.g. quota exceeded returns {code:7, msg:"..."})
        if (!text.startsWith('data: ')) {
          try {
            const json = JSON.parse(text);
            if (json.code && json.code !== 200 && json.msg) {
              this._updateAiMsg(aiMsgId, '⚠️ ' + json.msg);
              this.setData({ isTyping: false });
              this._fetchQuota();
              return;
            }
          } catch (_) { /* not JSON, continue SSE parsing */ }
        }

        const lines = text.split('\n');

        for (const line of lines) {
          if (!line.startsWith('data: ')) continue;
          const chunk = line.substring(6);

          if (chunk === '[DONE]') {
            this.setData({ isTyping: false });
            return;
          }
          if (chunk.startsWith('[ERROR]')) {
            fullText += '\n⚠️ ' + (chunk.substring(7) || '服务异常');
            this._updateAiMsg(aiMsgId, fullText);
            this.setData({ isTyping: false });
            return;
          }

          fullText += chunk;
          this._updateAiMsg(aiMsgId, fullText);
        }
        this.scrollToBottom();
      },
      onDone: () => {
        this.setData({ isTyping: false });
        this.scrollToBottom();
        // Delay: backend saves history async (go func) after stream ends
        setTimeout(() => this._fetchQuota(), 800);
      },
      onError: () => {
        this._updateAiMsg(aiMsgId, '网络连接失败，请稍后重试');
        this.setData({ isTyping: false });
      },
    });
  },

  _updateAiMsg(id, content) {
    const idx = this.data.messages.findIndex(m => m.id === id);
    if (idx !== -1) {
      this.setData({ [`messages[${idx}].content`]: this._cleanMd(content) });
    }
  },

  // Strip residual markdown symbols for clean display
  _cleanMd(text) {
    return text
      .replace(/^#{1,6}\s*/gm, '')          // ### headers
      .replace(/\*\*(.+?)\*\*/g, '【$1】')   // **bold** → 【bold】
      .replace(/\*(.+?)\*/g, '$1')           // *italic*
      .replace(/^[\-\*]\s+/gm, '· ')         // - list → · list
      .replace(/^\d+\.\s+/gm, (m) => m)      // keep numbered lists
      .replace(/`([^`]+)`/g, '$1')            // `code`
      .replace(/^---+$/gm, '————')            // --- → ————
      .replace(/\n{3,}/g, '\n\n');            // collapse blank lines
  },

  _decode(buffer) {
    try {
      return new TextDecoder('utf-8').decode(new Uint8Array(buffer));
    } catch (e) {
      const bytes = new Uint8Array(buffer);
      let s = '';
      for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
      try { return decodeURIComponent(escape(s)); } catch (_) { return s; }
    }
  },

  scrollToBottom() {
    this.setData({ scrollAnchor: 'scroll-bottom' });
  },
});
