const express = require("express");
const router = express.Router();
const steedosAuth = require('@steedos/auth');
const axios = require('axios');
const bodyParser = require('body-parser');
const { buildFormDesignSystemPrompt } = require('./buildFormDesignSystemPrompt');

router.use(bodyParser.json({ limit: '20mb' }));

/**
 * Streaming AI Form Designer endpoint (SSE)
 *
 * Same logic as /am/ai/form-design but uses Server-Sent Events to stream
 * progress updates so the client can show intermediate status.
 *
 * Events sent:
 *   { event: "progress", data: { stage: string, message: string } }
 *   { event: "chunk",    data: { text: string, accumulated: string } }  – raw AI text chunks
 *   { event: "result",   data: { ...final JSON result } }
 *   { event: "error",    data: { error: string } }
 *   { event: "done",     data: {} }
 */
router.post('/am/ai/form-design-stream', async function auth(req, res, next) {
  try {
    const result = await steedosAuth.auth(req, res);
    if (result && result.userId) {
      req.user = result;
      next();
    } else {
      res.status(401).json({ error: '请先登录' });
    }
  } catch (e) {
    res.status(401).json({ error: '认证失败' });
  }
}, async function (req, res) {
  // ---------- Set up SSE headers ----------
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  res.setHeader('X-Accel-Buffering', 'no'); // nginx
  res.flushHeaders();

  /** Helper: send an SSE event */
  function sendEvent(event, data) {
    if (res.writableEnded) return;
    res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
    // Flush if available (for compression middleware etc.)
    if (typeof res.flush === 'function') res.flush();
  }

  // If client disconnects early, stop writing
  let aborted = false;
  req.on('close', () => { aborted = true; });

  try {
    const apiKey = process.env.WORKFLOW_AI_API_KEY;
    if (!apiKey) {
      sendEvent('error', { error: '请先配置环境变量 WORKFLOW_AI_API_KEY' });
      sendEvent('done', {});
      return res.end();
    }

    const baseURL = process.env.WORKFLOW_AI_BASE_URL || 'https://api.openai.com/v1';
    const model = process.env.WORKFLOW_AI_MODEL || 'gpt-4o';

    const { fields, events, userRequest, images, instance_template, form_script, flow_events, chineseFieldNames, isUpgrade } = req.body;

    if (!userRequest) {
      sendEvent('error', { error: '请输入需求描述' });
      sendEvent('done', {});
      return res.end();
    }

    // ---- Build system prompt (same as non-streaming endpoint) ----
    sendEvent('progress', { stage: 'prepare', message: '正在准备请求...' });

    const systemPrompt = buildFormDesignSystemPrompt({ chineseFieldNames: !!chineseFieldNames, isUpgrade: !!isUpgrade });

    // Build current fields description
    const fieldsJson = JSON.stringify(fields || [], null, 2);
    const eventsJson = JSON.stringify(events || {}, null, 2);

    let extraSections = '';
    if (instance_template) {
      extraSections += `\n\n## 审批单模板 (instance_template)\n\`\`\`html\n${instance_template}\n\`\`\``;
    }
    if (form_script) {
      extraSections += `\n\n## 表单脚本 (form_script)\n\`\`\`javascript\n${form_script}\n\`\`\``;
    }
    if (flow_events) {
      extraSections += `\n\n## 流程事件 (flow_events)\n\`\`\`javascript\n${flow_events}\n\`\`\``;
    }

    const userContent = `## 当前表单字段\n${fieldsJson}\n\n## 当前事件脚本\n${eventsJson}${extraSections}\n\n## 用户需求\n${userRequest}\n\n请返回修改后的完整 JSON 对象（包含 tableColumns、fields 和 events）。`;

    let userMessageContent;
    if (Array.isArray(images) && images.length > 0) {
      userMessageContent = [
        { type: 'text', text: userContent },
        ...images.slice(0, 5).map(img => ({
          type: 'image_url',
          image_url: { url: img, detail: 'auto' },
        })),
      ];
    } else {
      userMessageContent = userContent;
    }

    if (aborted) return res.end();

    // ---- Call LLM with streaming ----
    sendEvent('progress', { stage: 'calling', message: '正在连接 AI 服务...' });

    // Log messages sent to AI
    const aiMessages = [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: typeof userMessageContent === 'string' ? userMessageContent : JSON.stringify(userMessageContent).slice(0, 2000) + '...' },
    ];
    console.log('===== AI Form Design - Messages sent to AI =====');
    console.log('System prompt length:', systemPrompt.length);
    console.log('User message type:', typeof userMessageContent === 'string' ? 'text' : 'multipart (with images)');
    console.log('User message length:', typeof userMessageContent === 'string' ? userMessageContent.length : JSON.stringify(userMessageContent).length);
    console.log('System prompt:\n', systemPrompt);
    console.log('User message:\n', typeof userMessageContent === 'string' ? userMessageContent : JSON.stringify(userMessageContent, null, 2));
    console.log('===== End of AI Messages =====');

    let accumulated = '';
    let chunkCount = 0;

    try {
      const streamResponse = await axios.post(`${baseURL}/chat/completions`, {
        model,
        messages: [
          { role: 'system', content: systemPrompt },
          { role: 'user', content: userMessageContent },
        ],
        temperature: 0.3,
        max_tokens: 16000,
        stream: true,
      }, {
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
        timeout: 300000,
        responseType: 'stream',
      });

      sendEvent('progress', { stage: 'streaming', message: 'AI 正在生成内容...' });

      // Process the SSE stream from OpenAI
      await new Promise((resolve, reject) => {
        let buffer = '';

        streamResponse.data.on('data', (chunk) => {
          if (aborted) {
            streamResponse.data.destroy();
            return resolve();
          }

          buffer += chunk.toString();
          const lines = buffer.split('\n');
          // Keep the last (potentially incomplete) line in the buffer
          buffer = lines.pop() || '';

          for (const line of lines) {
            const trimmed = line.trim();
            if (!trimmed || trimmed === 'data: [DONE]') continue;
            if (!trimmed.startsWith('data: ')) continue;

            try {
              const json = JSON.parse(trimmed.slice(6));
              const delta = json.choices?.[0]?.delta?.content;
              if (delta) {
                accumulated += delta;
                chunkCount++;
                // Send chunk text on every chunk so client can display live output
                sendEvent('chunk', {
                  text: delta,
                  accumulated: accumulated,
                });
              }
            } catch (_) {
              // Ignore parse errors in stream chunks
            }
          }
        });

        streamResponse.data.on('end', () => {
          // Process any remaining buffer
          if (buffer.trim() && buffer.trim() !== 'data: [DONE]' && buffer.trim().startsWith('data: ')) {
            try {
              const json = JSON.parse(buffer.trim().slice(6));
              const delta = json.choices?.[0]?.delta?.content;
              if (delta) accumulated += delta;
            } catch (_) {}
          }
          resolve();
        });

        streamResponse.data.on('error', (err) => {
          reject(err);
        });
      });

    } catch (streamErr) {
      // If streaming fails, fall back to non-streaming call
      if (streamErr.response && streamErr.response.status) {
        const status = streamErr.response.status;
        if (status === 401 || status === 403) {
          sendEvent('error', { error: 'AI API 密钥无效或权限不足，请检查 WORKFLOW_AI_API_KEY' });
          sendEvent('done', {});
          return res.end();
        }
        if (status === 429) {
          sendEvent('error', { error: 'AI API 请求频率超限，请稍后重试' });
          sendEvent('done', {});
          return res.end();
        }
      }

      sendEvent('progress', { stage: 'fallback', message: '流式传输不可用，切换为普通请求...' });

      try {
        const fallbackResponse = await axios.post(`${baseURL}/chat/completions`, {
          model,
          messages: [
            { role: 'system', content: systemPrompt },
            { role: 'user', content: userMessageContent },
          ],
          temperature: 0.3,
          max_tokens: 16000,
        }, {
          headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json',
          },
          timeout: 300000,
        });

        accumulated = fallbackResponse.data?.choices?.[0]?.message?.content || '';
      } catch (fallbackErr) {
        const errMsg = fallbackErr?.response?.data?.error?.message || fallbackErr?.message || 'AI 服务调用失败';
        sendEvent('error', { error: errMsg });
        sendEvent('done', {});
        return res.end();
      }
    }

    if (aborted) return res.end();

    if (!accumulated) {
      sendEvent('error', { error: 'AI 未返回有效内容' });
      sendEvent('done', {});
      return res.end();
    }

    // ---- Parse JSON ----
    sendEvent('progress', { stage: 'parsing', message: `正在解析 AI 返回内容 (${accumulated.length} 字符)...` });

    let result;
    try {
      let text = accumulated.trim();
      if (text.startsWith('```json')) text = text.slice(7);
      else if (text.startsWith('```')) text = text.slice(3);
      if (text.endsWith('```')) text = text.slice(0, -3);
      text = text.trim();

      const objStart = text.indexOf('{');
      const objEnd = text.lastIndexOf('}');
      if (objStart !== -1 && objEnd > objStart) {
        result = JSON.parse(text.substring(objStart, objEnd + 1));
      } else {
        result = JSON.parse(text);
      }
    } catch (parseErr) {
      sendEvent('error', { error: 'AI 返回内容无法解析为 JSON', raw: accumulated });
      sendEvent('done', {});
      return res.end();
    }

    // ---- Validate ----
    sendEvent('progress', { stage: 'validating', message: '正在验证和修正字段数据...' });

    if (!result || typeof result !== 'object') {
      sendEvent('error', { error: 'AI 返回的不是有效的 JSON 对象' });
      sendEvent('done', {});
      return res.end();
    }

    if (Array.isArray(result)) {
      result = { fields: result, events: events || {} };
    }

    if (result.fields && !Array.isArray(result.fields)) {
      sendEvent('error', { error: 'AI 返回的 fields 不是数组' });
      sendEvent('done', {});
      return res.end();
    }

    // Validate field types
    const validTypes = [
      'text', 'textarea', 'number', 'date', 'datetime', 'time',
      'select', 'multiSelect', 'checkbox', 'radio', 'file', 'image',
      'lookup', 'section', 'table', 'grid', 'formula',
      'member', 'memberMulti', 'org', 'orgMulti', 'reference', 'richtext'
    ];
    const jsIdentifierRe = /^[^\s{}][^{}]*$/;
    function sanitizeName(name) {
      if (!name) return 'field_' + Math.random().toString(36).slice(2, 6);
      // Only remove curly braces (reserved for formula variable references)
      let s = String(name).replace(/[{}]/g, '');
      return s.trim() || 'field_' + Math.random().toString(36).slice(2, 6);
    }

    if (result.fields) {
      for (const field of result.fields) {
        // Backward compat: map legacy userPicker/groupPicker to new types
        if (field.type === 'userPicker') field.type = field.pickerMultiple ? 'memberMulti' : 'member';
        if (field.type === 'groupPicker') field.type = field.pickerMultiple ? 'orgMulti' : 'org';
        // Backward compat: map legacy select + pickerMultiple to multiSelect
        if (field.type === 'select' && field.pickerMultiple) field.type = 'multiSelect';
        // Backward compat: map legacy html type to richtext
        if (field.type === 'html') field.type = 'richtext';
        if (field.type && !validTypes.includes(field.type)) {
          field.type = 'text';
        }
        if (field.name && !jsIdentifierRe.test(field.name)) {
          field.name = sanitizeName(field.name);
        }
        // Remove colspan/tableColspan from AI output — layout is determined by field type defaults
        delete field.colspan;
        delete field.tableColspan;
        if (field.type === 'table' && Array.isArray(field.children)) {
          for (const child of field.children) {
            // Backward compat: map legacy types in children
            if (child.type === 'userPicker') child.type = child.pickerMultiple ? 'memberMulti' : 'member';
            if (child.type === 'groupPicker') child.type = child.pickerMultiple ? 'orgMulti' : 'org';
            if (child.type === 'select' && child.pickerMultiple) child.type = 'multiSelect';
            // Backward compat: map legacy html type to richtext
            if (child.type === 'html') child.type = 'richtext';
            if (child.type && !validTypes.includes(child.type)) {
              child.type = 'text';
            }
            if (child.name && !jsIdentifierRe.test(child.name)) {
              child.name = sanitizeName(child.name);
            }
            if (child.type === 'section' || child.type === 'table') {
              child.type = 'text';
            }
          }
        }
      }
    }

    if (!result.events || typeof result.events !== 'object') {
      result.events = events || {};
    }

    // Build response
    const responseData = {
      fields: result.fields || fields || [],
      tableColumns: typeof result.tableColumns === 'number' ? result.tableColumns : undefined,
      events: {
        onInit: result.events.onInit || '',
        onValueChange: result.events.onValueChange || '',
        onSubmit: result.events.onSubmit || '',
      },
    };
    // Pass through migrationLog if present (for upgrade audit trail)
    if (Array.isArray(result.migrationLog) && result.migrationLog.length > 0) {
      responseData.migrationLog = result.migrationLog;
    }

    const fieldCount = (responseData.fields || []).length;
    sendEvent('progress', { stage: 'complete', message: `转换完成！共 ${fieldCount} 个字段` });
    sendEvent('result', responseData);
    sendEvent('done', {});
    return res.end();

  } catch (error) {
    console.error('AI form design stream error:', error?.response?.data || error?.message || error);
    if (!aborted) {
      const errData = error?.response?.data;
      const status = error?.response?.status;
      let errMsg;
      if (status === 401 || status === 403) {
        errMsg = 'AI API 密钥无效或权限不足，请检查 WORKFLOW_AI_API_KEY';
      } else if (status === 429) {
        errMsg = 'AI API 请求频率超限，请稍后重试';
      } else {
        errMsg = errData?.error?.message || error?.message || 'AI 服务调用失败';
      }
      sendEvent('error', { error: errMsg });
      sendEvent('done', {});
    }
    return res.end();
  }
});

exports.default = router;
