const express = require('express');
const prisma = require('../lib/prisma');
const { adminAuthMiddleware } = require('../lib/auth');
const { generateSyncToken } = require('../lib/sync-token');
const { postSync } = require('../lib/hermes-client');

const router = express.Router();

// SSRF 防护：校验 webhookUrl 协议与主机
// - 仅允许 http/https（开发环境允许 http，生产环境强制 https）
// - 禁止指向内网/回环地址（10.x、127.x、169.254.x、172.16-31.x、192.168.x、::1、fc00::/7）
function isPrivateIPv4(hostname) {
  const parts = hostname.split('.').map(Number);
  if (parts.length !== 4 || parts.some((p) => Number.isNaN(p))) return false;
  const [a, b] = parts;
  if (a === 10) return true;
  if (a === 127) return true;
  if (a === 169 && b === 254) return true;
  if (a === 172 && b >= 16 && b <= 31) return true;
  if (a === 192 && b === 168) return true;
  if (a === 0) return true;
  return false;
}

function validateWebhookUrl(rawUrl) {
  if (!rawUrl || typeof rawUrl !== 'string') {
    return { ok: false, error: 'webhook URL 不能为空' };
  }
  let url;
  try {
    url = new URL(rawUrl);
  } catch {
    return { ok: false, error: 'webhook URL 格式无效' };
  }
  const hostname = url.hostname.toLowerCase();
  if (url.protocol !== 'https:' && url.protocol !== 'http:') {
    return { ok: false, error: 'webhook URL 协议仅支持 http/https' };
  }
  const isProduction = process.env.NODE_ENV === 'production';
  if (isProduction && url.protocol !== 'https:') {
    return { ok: false, error: '生产环境 webhook URL 必须使用 https' };
  }
  // 生产环境禁止指向内网/回环地址（SSRF 防护）
  // 非生产环境允许 localhost（用于 mock-hermes 测试）
  if (isProduction) {
    if (isPrivateIPv4(hostname)) {
      return { ok: false, error: 'webhook URL 不允许指向内网地址' };
    }
    if (hostname === 'localhost' || hostname === '::1' || hostname.endsWith('.local')) {
      return { ok: false, error: 'webhook URL 不允许指向本地地址' };
    }
    if (hostname.startsWith('fc') || hostname.startsWith('fd') || hostname.startsWith('fe80')) {
      return { ok: false, error: 'webhook URL 不允许指向内网地址' };
    }
  }
  return { ok: true, url };
}

// 管理员发起同步
router.post('/:roleId', adminAuthMiddleware, async (req, res) => {
  try {
    const {
      profileName,
      modelKey,
      provider,
      multimediaModelKey,
      multimediaProvider,
      enableSchedule,
      webhookUrl,
    } = req.body;

    if (!profileName) {
      return res.status(400).json({ error: 'profile 名字不能为空' });
    }

    const role = await prisma.role.findUnique({ where: { id: req.params.roleId } });
    if (!role) {
      return res.status(404).json({ error: '角色不存在' });
    }
    if (!['approved', 'failed'].includes(role.reviewStatus)) {
      return res.status(400).json({ error: `当前状态为 ${role.reviewStatus}，无法同步（需 approved 或 failed）` });
    }

    // 获取 Hermes webhook URL：优先用请求参数，否则用全局配置
    let hermesUrl = webhookUrl;
    if (!hermesUrl) {
      const config = await prisma.systemConfig.findUnique({ where: { key: 'HERMES_WEBHOOK_URL' } });
      hermesUrl = config?.value;
    }
    if (!hermesUrl) {
      return res.status(400).json({ error: '未配置 Hermes webhook URL' });
    }

    // SSRF 防护：校验 webhookUrl
    const urlCheck = validateWebhookUrl(hermesUrl);
    if (!urlCheck.ok) {
      return res.status(400).json({ error: urlCheck.error });
    }
    hermesUrl = urlCheck.url.toString();

    // 获取 EternalAI 自身基础 URL（供 Hermes 回调拉取文件）
    // 优先使用环境变量 BASE_URL，避免 Host 头被伪造
    const baseUrl = process.env.BASE_URL || (req.protocol + '://' + req.get('host'));

    // 生成 sync_token
    const syncToken = await generateSyncToken(role.id, req.adminId);

    // 更新状态为 syncing
    await prisma.role.update({
      where: { id: role.id },
      data: { reviewStatus: 'syncing' },
    });

    // 向 Hermes POST 同步请求
    const payload = {
      profileName,
      modelKey,
      provider,
      multimediaModelKey,
      multimediaProvider,
      enableSchedule: !!enableSchedule,
      syncToken,
      filePullBaseUrl: baseUrl,
      roleId: role.id,
    };

    const result = await postSync(hermesUrl, payload);

    // 同步成功，存储二维码 URL
    const updated = await prisma.role.update({
      where: { id: role.id },
      data: {
        reviewStatus: 'synced',
        qrCodeUrl: result.qrCodeUrl || null,
        syncedAt: new Date(),
      },
      select: {
        id: true,
        displayName: true,
        reviewStatus: true,
        qrCodeUrl: true,
        syncedAt: true,
      },
    });

    res.json({ role: updated, profileId: result.profileId });
  } catch (err) {
    console.error('同步失败:', err);

    // 同步失败，仅当当前状态为 syncing 时才回滚为 failed（避免误覆盖 approved）
    try {
      const current = await prisma.role.findUnique({
        where: { id: req.params.roleId },
        select: { reviewStatus: true },
      });
      if (current && current.reviewStatus === 'syncing') {
        await prisma.role.update({
          where: { id: req.params.roleId },
          data: { reviewStatus: 'failed' },
        });
      }
    } catch (updateErr) {
      console.error('更新失败状态出错:', updateErr);
    }

    res.status(500).json({ error: '同步失败，请稍后重试或检查 Hermes 服务状态' });
  }
});

// 管理员强制重置 syncing 卡死状态（恢复路径）
router.post('/:roleId/reset', adminAuthMiddleware, async (req, res) => {
  try {
    const role = await prisma.role.findUnique({ where: { id: req.params.roleId } });
    if (!role) {
      return res.status(404).json({ error: '角色不存在' });
    }
    if (role.reviewStatus !== 'syncing') {
      return res.status(400).json({ error: `当前状态为 ${role.reviewStatus}，仅 syncing 状态可重置` });
    }
    const updated = await prisma.role.update({
      where: { id: req.params.roleId },
      data: { reviewStatus: 'failed' },
      select: { id: true, displayName: true, reviewStatus: true },
    });
    res.json({ role: updated });
  } catch (err) {
    console.error('重置同步状态失败:', err);
    res.status(500).json({ error: '重置失败' });
  }
});

module.exports = router;
