'use strict';

const crypto = require('crypto');
const axios = require('axios');
const { URL } = require('url');

// ─── 常量 ───
const SESSION_EXPIRE_MS = 7 * 24 * 60 * 60 * 1000; // 7天
const TOKEN_BYTES = 32;
const OWNER_EMAIL = (process.env.ZY_OWNER_EMAIL || '565183519@qq.com').trim().toLowerCase();

// ─── GitHub OAuth 配置 ───
const GITHUB_CLIENT_ID = process.env.ZY_GITHUB_CLIENT_ID;
const GITHUB_CLIENT_SECRET = process.env.ZY_GITHUB_CLIENT_SECRET;
const GITHUB_REDIRECT_URI = process.env.ZY_GITHUB_REDIRECT_URI || 'http://localhost:3800/auth/github/callback';

// ─── Notion OAuth 配置 ───
const NOTION_CLIENT_ID = process.env.ZY_NOTION_CLIENT_ID;
const NOTION_CLIENT_SECRET = process.env.ZY_NOTION_CLIENT_SECRET;
const NOTION_REDIRECT_URI = process.env.ZY_NOTION_REDIRECT_URI || 'http://localhost:3800/auth/notion/callback';

// ─── 内存存储 ───
const pendingStates = new Map();   // state → { provider, createdAt }
const activeSessions = new Map(); // token → { email, provider, createdAt, expiresAt }

/**
 * 生成安全state参数（防CSRF）
 */
function generateState() {
  return crypto.randomBytes(16).toString('hex');
}

/**
 * 生成安全session token
 */
function generateToken() {
  return crypto.randomBytes(TOKEN_BYTES).toString('hex');
}

/**
 * GitHub OAuth 授权URL
 */
function getGitHubAuthUrl() {
  if (!GITHUB_CLIENT_ID) throw new Error('GitHub OAuth未配置: 需要ZY_GITHUB_CLIENT_ID环境变量');
  
  const state = generateState();
  const url = new URL('https://github.com/login/oauth/authorize');
  url.searchParams.set('client_id', GITHUB_CLIENT_ID);
  url.searchParams.set('redirect_uri', GITHUB_REDIRECT_URI);
  url.searchParams.set('state', state);
  url.searchParams.set('scope', 'user:email');
  
  pendingStates.set(state, {
    provider: 'github',
    createdAt: Date.now()
  });
  
  return url.toString();
}

/**
 * Notion OAuth 授权URL
 */
function getNotionAuthUrl() {
  if (!NOTION_CLIENT_ID) throw new Error('Notion OAuth未配置: 需要ZY_NOTION_CLIENT_ID环境变量');
  
  const state = generateState();
  const url = new URL('https://api.notion.com/v1/oauth/authorize');
  url.searchParams.set('client_id', NOTION_CLIENT_ID);
  url.searchParams.set('redirect_uri', NOTION_REDIRECT_URI);
  url.searchParams.set('state', state);
  url.searchParams.set('response_type', 'code');
  
  pendingStates.set(state, {
    provider: 'notion',
    createdAt: Date.now()
  });
  
  return url.toString();
}

/**
 * 验证state参数
 */
function validateState(state, provider) {
  if (!state || !provider) return false;
  
  const pending = pendingStates.get(state);
  if (!pending) return false;
  
  // 检查provider匹配
  if (pending.provider !== provider) return false;
  
  // 检查过期（10分钟）
  if (Date.now() - pending.createdAt > 10 * 60 * 1000) {
    pendingStates.delete(state);
    return false;
  }
  
  // 验证通过后清理state
  pendingStates.delete(state);
  return true;
}

/**
 * GitHub OAuth 回调处理
 */
async function handleGitHubCallback(code, state) {
  if (!validateState(state, 'github')) {
    throw new Error('无效的state参数');
  }
  
  if (!GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET) {
    throw new Error('GitHub OAuth未配置');
  }
  
  // 1. 获取access token
  const tokenRes = await axios.post(
    'https://github.com/login/oauth/access_token',
    {
      client_id: GITHUB_CLIENT_ID,
      client_secret: GITHUB_CLIENT_SECRET,
      code,
      redirect_uri: GITHUB_REDIRECT_URI
    },
    {
      headers: { Accept: 'application/json' }
    }
  );
  
  if (!tokenRes.data.access_token) {
    throw new Error('GitHub token获取失败');
  }
  
  // 2. 获取用户邮箱
  const userRes = await axios.get('https://api.github.com/user/emails', {
    headers: {
      Authorization: `token ${tokenRes.data.access_token}`,
      Accept: 'application/vnd.github.v3+json'
    }
  });
  
  // 3. 查找主邮箱
  const primaryEmail = userRes.data.find(e => e.primary)?.email;
  if (!primaryEmail) {
    throw new Error('无法获取GitHub主邮箱');
  }
  
  // 4. 主权验证
  const normalizedEmail = primaryEmail.trim().toLowerCase();
  if (normalizedEmail !== OWNER_EMAIL) {
    throw new Error('此频道为专属频道，仅限频道主权持有者登录');
  }
  
  // 5. 创建session
  const token = generateToken();
  const expiresAt = Date.now() + SESSION_EXPIRE_MS;
  
  activeSessions.set(token, {
    email: normalizedEmail,
    provider: 'github',
    createdAt: Date.now(),
    expiresAt
  });
  
  return {
    token,
    email: normalizedEmail,
    provider: 'github',
    expiresAt: new Date(expiresAt).toISOString()
  };
}

/**
 * Notion OAuth 回调处理
 */
async function handleNotionCallback(code, state) {
  if (!validateState(state, 'notion')) {
    throw new Error('无效的state参数');
  }
  
  if (!NOTION_CLIENT_ID || !NOTION_CLIENT_SECRET) {
    throw new Error('Notion OAuth未配置');
  }
  
  // 1. 获取access token
  const tokenRes = await axios.post(
    'https://api.notion.com/v1/oauth/token',
    {
      grant_type: 'authorization_code',
      code,
      redirect_uri: NOTION_REDIRECT_URI
    },
    {
      auth: {
        username: NOTION_CLIENT_ID,
        password: NOTION_CLIENT_SECRET
      },
      headers: { 'Content-Type': 'application/json' }
    }
  );
  
  if (!tokenRes.data.access_token) {
    throw new Error('Notion token获取失败');
  }
  
  // 2. 获取用户信息
  const userRes = await axios.get('https://api.notion.com/v1/users/me', {
    headers: {
      Authorization: `Bearer ${tokenRes.data.access_token}`,
      'Notion-Version': '2022-06-28'
    }
  });
  
  // 3. 提取邮箱
  const email = userRes.data.bot?.owner?.user?.email || userRes.data.person?.email;
  if (!email) {
    throw new Error('无法获取Notion邮箱');
  }
  
  // 4. 主权验证
  const normalizedEmail = email.trim().toLowerCase();
  if (normalizedEmail !== OWNER_EMAIL) {
    throw new Error('此频道为专属频道，仅限频道主权持有者登录');
  }
  
  // 5. 创建session
  const token = generateToken();
  const expiresAt = Date.now() + SESSION_EXPIRE_MS;
  
  activeSessions.set(token, {
    email: normalizedEmail,
    provider: 'notion',
    createdAt: Date.now(),
    expiresAt
  });
  
  return {
    token,
    email: normalizedEmail,
    provider: 'notion',
    expiresAt: new Date(expiresAt).toISOString()
  };
}

/**
 * 验证session token
 */
function validateSession(token) {
  if (!token || typeof token !== 'string') {
    return { valid: false };
  }
  
  const session = activeSessions.get(token);
  if (!session) {
    return { valid: false };
  }
  
  if (Date.now() > session.expiresAt) {
    activeSessions.delete(token);
    return { valid: false };
  }
  
  return {
    valid: true,
    email: session.email,
    provider: session.provider,
    expiresAt: new Date(session.expiresAt).toISOString()
  };
}

/**
 * 注销session
 */
function revokeSession(token) {
  activeSessions.delete(token);
}

module.exports = {
  getGitHubAuthUrl,
  getNotionAuthUrl,
  handleGitHubCallback,
  handleNotionCallback,
  validateSession,
  revokeSession
};