/**
 * GLADA · 通知器 · notifier.js
 *
 * 多通道通知系统：
 *   1. QQ邮箱 SMTP 通知（主通道·已打通）
 *   2. 企业微信推送（预留通道·冰朔开通后接入）
 *   3. 文件日志通知（本地记录·始终启用）
 *
 * 通知内容包含：
 *   - 任务编号 + 标题
 *   - 完成步骤列表
 *   - 变更文件清单
 *   - 测试结果
 *   - 开发回执（git branch + commits）
 *
 * 环境变量：
 *   ZY_SMTP_USER        - QQ邮箱账号（同零点原核的SMTP）
 *   ZY_SMTP_PASS        - QQ邮箱授权码
 *   GLADA_NOTIFY_TO     - 通知接收邮箱（默认 = ZY_SMTP_USER）
 *   WECOM_WEBHOOK       - 企业微信机器人 Webhook（可选·预留）
 *
 * 版权：国作登字-2026-A-00037559
 * 签发：铸渊 · ICE-GL-ZY001
 */

'use strict';

const https = require('https');
const http = require('http');
const fs = require('fs');
const path = require('path');
const nodemailer = require('nodemailer');

const ROOT = path.resolve(__dirname, '..');
const NOTIFICATION_LOG_DIR = path.join(ROOT, 'glada', 'logs', 'notifications');

// ── SMTP 传输器（懒初始化，复用零点原核频道的 QQ 邮箱配置） ──

let _transporter = null;

function getSmtpTransporter() {
  if (_transporter) return _transporter;

  const smtpUser = process.env.ZY_SMTP_USER;
  const smtpPass = process.env.ZY_SMTP_PASS;

  if (!smtpUser || !smtpPass) {
    return null;
  }

  _transporter = nodemailer.createTransport({
    host: 'smtp.qq.com',
    port: 465,
    secure: true,
    auth: {
      user: smtpUser,
      pass: smtpPass
    },
    tls: {
      rejectUnauthorized: true
    }
  });

  return _transporter;
}

/**
 * HTTP 请求工具（用于企业微信等 Webhook 通道）
 */
function httpRequest(url, options, body) {
  return new Promise((resolve, reject) => {
    const parsed = new URL(url);
    const isHttps = parsed.protocol === 'https:';
    const mod = isHttps ? https : http;

    const opts = {
      hostname: parsed.hostname,
      port: parsed.port || (isHttps ? 443 : 80),
      path: parsed.pathname + parsed.search,
      method: options.method || 'POST',
      headers: options.headers || {},
      timeout: options.timeout || 30000,
    };

    const req = mod.request(opts, (res) => {
      let data = '';
      res.on('data', (chunk) => { data += chunk; });
      res.on('end', () => resolve({ status: res.statusCode, body: data }));
    });

    req.on('error', reject);
    req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });

    if (body) req.write(body);
    req.end();
  });
}

/**
 * 构建通知内容
 * @param {Object} gladaTask - GLADA 任务
 * @param {string} eventType - 事件类型: completed | failed | step_completed | started
 * @returns {Object} { subject, body, html }
 */
function buildNotification(gladaTask, eventType) {
  const taskId = gladaTask.glada_task_id;
  const title = gladaTask.plan.title;
  const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });

  const steps = gladaTask.plan.steps || [];
  const completedSteps = steps.filter(s => s.status === 'completed');
  const failedSteps = steps.filter(s => s.status === 'failed' || s.status === 'rolled_back');

  const allFilesChanged = gladaTask.completion?.total_files_changed || [];
  const gitBranch = gladaTask.completion?.git_branch || '未知';
  const gitCommits = gladaTask.completion?.git_commits || [];

  let subject = '';
  let body = '';

  switch (eventType) {
    case 'completed':
      subject = `✅ GLADA任务完成: ${taskId} · ${title}`;
      body = [
        `🎉 GLADA 任务已完成`,
        ``,
        `任务编号: ${taskId}`,
        `任务标题: ${title}`,
        `完成时间: ${now}`,
        ``,
        `📊 执行概况:`,
        `  - 总步骤: ${steps.length}`,
        `  - 已完成: ${completedSteps.length}`,
        `  - 失败: ${failedSteps.length}`,
        ``,
        `📁 变更文件 (${allFilesChanged.length}):`,
        ...allFilesChanged.map(f => `  - ${f}`),
        ``,
        `🌿 Git 分支: ${gitBranch}`,
        `📝 提交记录:`,
        ...gitCommits.map(c => `  - ${c}`),
        ``,
        `请打开副驾驶验收: "GLADA任务 ${taskId} 已完成，请验收"`,
      ].join('\n');
      break;

    case 'failed':
      subject = `❌ GLADA任务失败: ${taskId} · ${title}`;
      body = [
        `⚠️ GLADA 任务执行失败`,
        ``,
        `任务编号: ${taskId}`,
        `任务标题: ${title}`,
        `失败时间: ${now}`,
        ``,
        `📊 执行概况:`,
        `  - 总步骤: ${steps.length}`,
        `  - 已完成: ${completedSteps.length}`,
        `  - 失败: ${failedSteps.length}`,
        ``,
        `❌ 失败步骤:`,
        ...failedSteps.map(s => `  - 步骤${s.step_id}: ${s.description} (${s.error || '未知错误'})`),
        ``,
        `请打开副驾驶排查: "GLADA任务 ${taskId} 失败了，请帮我排查"`,
      ].join('\n');
      break;

    case 'step_completed':
      subject = `📋 GLADA进度: ${taskId} · 步骤${completedSteps.length}/${steps.length}`;
      body = [
        `GLADA 步骤完成通知`,
        ``,
        `任务: ${title}`,
        `进度: ${completedSteps.length}/${steps.length}`,
        `时间: ${now}`,
      ].join('\n');
      break;

    case 'started':
      subject = `🚀 GLADA任务开始: ${taskId} · ${title}`;
      body = [
        `GLADA 任务已开始执行`,
        ``,
        `任务编号: ${taskId}`,
        `任务标题: ${title}`,
        `总步骤: ${steps.length}`,
        `开始时间: ${now}`,
      ].join('\n');
      break;

    default:
      subject = `GLADA: ${taskId}`;
      body = `任务 ${taskId} 状态更新: ${eventType}`;
  }

  // 生成 HTML 邮件格式
  const html = buildEmailHtml(subject, body, eventType, {
    taskId, title, now, steps, completedSteps, failedSteps,
    allFilesChanged, gitBranch, gitCommits
  });

  return { subject, body, html };
}

/**
 * 构建 GLADA 通知邮件 HTML（光湖视觉风格）
 */
function buildEmailHtml(subject, plainBody, eventType, data) {
  const statusColor = eventType === 'completed' ? '#22d3ee'
    : eventType === 'failed' ? '#f87171'
    : eventType === 'started' ? '#a78bfa'
    : '#60a5fa';

  const statusIcon = eventType === 'completed' ? '✅'
    : eventType === 'failed' ? '❌'
    : eventType === 'started' ? '🚀'
    : '📋';

  const filesHtml = (data.allFilesChanged || []).length > 0
    ? `<div style="margin:16px 0"><strong style="color:#94a3b8">📁 变更文件:</strong><ul style="margin:8px 0;padding-left:20px;color:#cbd5e1">${data.allFilesChanged.map(f => `<li style="margin:2px 0;font-family:monospace;font-size:12px">${f}</li>`).join('')}</ul></div>`
    : '';

  const commitsHtml = (data.gitCommits || []).length > 0
    ? `<div style="margin:16px 0"><strong style="color:#94a3b8">📝 提交记录:</strong><ul style="margin:8px 0;padding-left:20px;color:#cbd5e1">${data.gitCommits.map(c => `<li style="margin:2px 0;font-family:monospace;font-size:12px">${c}</li>`).join('')}</ul></div>`
    : '';

  const stepsHtml = (data.steps || []).length > 0
    ? `<div style="margin:16px 0"><strong style="color:#94a3b8">📊 步骤:</strong><ul style="margin:8px 0;padding-left:20px;color:#cbd5e1">${data.steps.map(s => {
        const icon = s.status === 'completed' ? '✅' : s.status === 'failed' || s.status === 'rolled_back' ? '❌' : '⏳';
        return `<li style="margin:2px 0">${icon} ${s.description || '步骤' + s.step_id}</li>`;
      }).join('')}</ul></div>`
    : '';

  return `<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>${subject}</title></head>
<body style="margin:0;padding:0;background:#050810;font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Helvetica Neue',sans-serif">
<main style="max-width:560px;margin:0 auto;padding:40px 24px">
  <div style="text-align:center;margin-bottom:24px">
    <div style="display:inline-block;width:48px;height:48px;line-height:48px;border-radius:12px;background:linear-gradient(135deg,rgba(34,211,238,0.15),rgba(167,139,250,0.12));border:1px solid rgba(96,165,250,0.2);font-size:20px;font-weight:900;color:#22d3ee;font-family:serif">渊</div>
  </div>
  <div style="background:rgba(10,16,36,0.95);border-radius:16px;border:1px solid rgba(96,165,250,0.1);padding:28px 24px">
    <div style="text-align:center;margin-bottom:20px">
      <span style="font-size:28px">${statusIcon}</span>
      <h2 style="color:#e2eaf8;font-size:16px;font-weight:700;margin:8px 0 4px">${data.title || ''}</h2>
      <p style="color:#7a8db8;font-size:12px;margin:0">任务 ${data.taskId} · ${data.now}</p>
    </div>
    <div style="background:rgba(${statusColor === '#22d3ee' ? '34,211,238' : statusColor === '#f87171' ? '248,113,113' : '167,139,250'},0.06);border:1px solid rgba(${statusColor === '#22d3ee' ? '34,211,238' : statusColor === '#f87171' ? '248,113,113' : '167,139,250'},0.15);border-radius:10px;padding:16px;margin-bottom:16px">
      <p style="color:${statusColor};font-weight:600;margin:0 0 8px;font-size:14px">${subject}</p>
      <p style="color:#94a3b8;font-size:13px;margin:0">总步骤: ${(data.steps || []).length} · 完成: ${(data.completedSteps || []).length} · 失败: ${(data.failedSteps || []).length}</p>
    </div>
    ${stepsHtml}
    ${filesHtml}
    ${data.gitBranch && data.gitBranch !== '未知' ? `<p style="color:#94a3b8;font-size:12px;margin:8px 0">🌿 分支: <code style="background:rgba(96,165,250,0.1);padding:2px 6px;border-radius:4px;color:#60a5fa">${data.gitBranch}</code></p>` : ''}
    ${commitsHtml}
  </div>
  <div style="text-align:center;margin-top:20px">
    <p style="color:rgba(100,130,180,0.4);font-size:10px;margin:0">铸渊 · GLADA 自主开发Agent · 自动发送</p>
    <p style="color:rgba(100,130,180,0.3);font-size:9px;margin:4px 0 0">版权 国作登字-2026-A-00037559 · TCS-0002∞</p>
  </div>
</main>
</body>
</html>`;
}

/**
 * 发送QQ邮箱通知（主通道）
 * @param {Object} notification - 通知内容 { subject, body, html }
 * @returns {Promise<boolean>}
 */
async function sendEmail(notification) {
  // ⚠️ D72 (2026-05-03) 冰朔决策：默认禁用所有邮件告警。
  // 与 ops-agent/notifier.js 行为一致：必须显式 OPS_EMAIL_ENABLED=true 才发。
  const v = process.env.OPS_EMAIL_ENABLED;
  const norm = v === undefined || v === null ? '' : String(v).trim().toLowerCase();
  const enabled = norm === 'true' || norm === '1' || norm === 'yes' || norm === 'on';
  if (!enabled) {
    console.log('[GLADA-Notify] OPS_EMAIL_ENABLED!=true (D72 默认禁用)，跳过邮件通知');
    return false;
  }

  const transporter = getSmtpTransporter();
  if (!transporter) {
    console.log('[GLADA-Notify] ⚠️ QQ邮箱 SMTP 未配置（需要 ZY_SMTP_USER + ZY_SMTP_PASS），跳过邮件通知');
    return false;
  }

  const smtpUser = process.env.ZY_SMTP_USER;
  const notifyTo = process.env.GLADA_NOTIFY_TO || smtpUser;

  try {
    const info = await transporter.sendMail({
      from: `"铸渊 · GLADA Agent" <${smtpUser}>`,
      to: notifyTo,
      subject: notification.subject,
      text: notification.body,
      html: notification.html
    });

    console.log(`[GLADA-Notify] 📧 邮件通知已发送: ${info.messageId}`);
    return true;
  } catch (err) {
    console.error(`[GLADA-Notify] 📧 邮件通知失败: ${err.message}`);
    return false;
  }
}

/**
 * 发送企业微信通知（预留通道·冰朔开通企业微信后接入）
 *
 * 企业微信机器人 Webhook 格式:
 *   https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
 *
 * @param {string} webhook - 企业微信 Webhook URL
 * @param {Object} notification - 通知内容
 * @returns {Promise<boolean>}
 */
async function sendWeCom(webhook, notification) {
  if (!webhook) {
    // 未配置时静默跳过（预留通道，不打印警告）
    return false;
  }

  try {
    const payload = JSON.stringify({
      msgtype: 'markdown',
      markdown: {
        content: [
          `### ${notification.subject}`,
          ``,
          notification.body.split('\n').map(line => `> ${line}`).join('\n')
        ].join('\n')
      }
    });

    const response = await httpRequest(webhook, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' }
    }, payload);

    const result = JSON.parse(response.body || '{}');
    const success = result.errcode === 0;
    console.log(`[GLADA-Notify] 💬 企业微信通知: ${success ? '✅' : '❌'} ${result.errmsg || ''}`);
    return success;
  } catch (err) {
    console.error(`[GLADA-Notify] 💬 企业微信通知失败: ${err.message}`);
    return false;
  }
}

/**
 * 写入本地通知日志
 * @param {Object} notification - 通知内容
 * @param {string} taskId - 任务 ID
 */
function writeNotificationLog(notification, taskId) {
  fs.mkdirSync(NOTIFICATION_LOG_DIR, { recursive: true });

  const logEntry = {
    timestamp: new Date().toISOString(),
    task_id: taskId,
    subject: notification.subject,
    body: notification.body,
    channels: []
  };

  const today = new Date().toISOString().split('T')[0];
  const logFile = path.join(NOTIFICATION_LOG_DIR, `notify-${today}.jsonl`);

  fs.appendFileSync(logFile, JSON.stringify(logEntry) + '\n', 'utf-8');
}

/**
 * 发送任务通知（所有通道）
 * @param {Object} gladaTask - GLADA 任务
 * @param {string} eventType - 事件类型
 * @returns {Promise<Object>} 发送结果
 */
async function notify(gladaTask, eventType) {
  const notification = buildNotification(gladaTask, eventType);
  const results = { channels: {} };

  console.log(`[GLADA-Notify] 📣 ${notification.subject}`);

  // 1. 本地日志（始终记录）
  writeNotificationLog(notification, gladaTask.glada_task_id);
  results.channels.log = true;

  // 2. QQ邮箱 SMTP（主通道）
  const smtpConfigured = !!(process.env.ZY_SMTP_USER && process.env.ZY_SMTP_PASS);
  if (smtpConfigured) {
    results.channels.email = await sendEmail(notification);
  }

  // 3. 企业微信（预留通道）
  const wecomWebhook = process.env.WECOM_WEBHOOK || process.env.GLADA_WECOM_WEBHOOK || '';
  if (wecomWebhook) {
    results.channels.wecom = await sendWeCom(wecomWebhook, notification);
  }

  // 4. 生成开发回执文件
  if (eventType === 'completed' || eventType === 'failed') {
    const receiptPath = path.join(ROOT, 'glada', 'receipts', `${gladaTask.glada_task_id}.json`);
    fs.mkdirSync(path.dirname(receiptPath), { recursive: true });
    fs.writeFileSync(receiptPath, JSON.stringify({
      task_id: gladaTask.glada_task_id,
      source_task_id: gladaTask.source_task_id,
      status: eventType,
      title: gladaTask.plan.title,
      completed_at: new Date().toISOString(),
      steps_summary: gladaTask.plan.steps.map(s => ({
        step_id: s.step_id,
        description: s.description,
        status: s.status
      })),
      files_changed: gladaTask.completion?.total_files_changed || [],
      git_branch: gladaTask.completion?.git_branch || null,
      git_commits: gladaTask.completion?.git_commits || [],
      notification: notification.subject
    }, null, 2), 'utf-8');

    results.channels.receipt = true;
    console.log(`[GLADA-Notify] 📄 开发回执: ${receiptPath}`);
  }

  return results;
}

module.exports = {
  buildNotification,
  sendEmail,
  sendWeCom,
  writeNotificationLog,
  notify
};
