import crypto from 'node:crypto';
import { config } from './config.js';
import { nowSeconds, safeEqual, sanitizeText } from './utils.js';

function telegramError(code, message, status = 401) {
  throw Object.assign(new Error(message), { code, status });
}

export function validateTelegramInitData(initData, maxAgeSeconds = 86400) {
  if (!config.telegramBotToken) telegramError('TELEGRAM_NOT_CONFIGURED', 'Telegram bot token is not configured.', 503);
  const params = new URLSearchParams(initData);
  const hash = params.get('hash');
  if (!hash) telegramError('INVALID_TELEGRAM_DATA', 'Telegram hash missing.');
  params.delete('hash');
  const dataCheckString = [...params.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([key, value]) => `${key}=${value}`)
    .join('\n');
  const secretKey = crypto.createHmac('sha256', 'WebAppData').update(config.telegramBotToken).digest();
  const computed = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex');
  if (!safeEqual(computed, hash)) telegramError('INVALID_TELEGRAM_DATA', 'Telegram signature invalid.');
  const authDate = Number(params.get('auth_date') || 0);
  if (!authDate || Math.abs(nowSeconds() - authDate) > maxAgeSeconds) telegramError('TELEGRAM_DATA_EXPIRED', 'Telegram authentication data expired.');
  let user;
  try { user = JSON.parse(params.get('user') || '{}'); } catch { user = {}; }
  if (!user.id) telegramError('INVALID_TELEGRAM_DATA', 'Telegram user missing.');
  return user;
}

export function validateTelegramLoginData(payload, maxAgeSeconds = 86400) {
  if (!config.telegramBotToken) telegramError('TELEGRAM_NOT_CONFIGURED', 'Telegram bot token is not configured.', 503);
  const allowed = ['id', 'first_name', 'last_name', 'username', 'photo_url', 'auth_date', 'phone_number'];
  const data = {};
  for (const key of allowed) if (payload?.[key] != null && payload[key] !== '') data[key] = String(payload[key]);
  const suppliedHash = String(payload?.hash || '').toLowerCase();
  if (!suppliedHash || !/^[a-f0-9]{64}$/.test(suppliedHash)) telegramError('INVALID_TELEGRAM_DATA', 'Telegram login hash missing.');
  const dataCheckString = Object.entries(data).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}=${value}`).join('\n');
  const secretKey = crypto.createHash('sha256').update(config.telegramBotToken).digest();
  const computed = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex');
  if (!safeEqual(computed, suppliedHash)) telegramError('INVALID_TELEGRAM_DATA', 'Telegram login signature invalid.');
  const authDate = Number(data.auth_date || 0);
  if (!authDate || Math.abs(nowSeconds() - authDate) > maxAgeSeconds) telegramError('TELEGRAM_DATA_EXPIRED', 'Telegram login data expired.');
  if (!data.id) telegramError('INVALID_TELEGRAM_DATA', 'Telegram user id missing.');
  return {
    id: data.id,
    first_name: sanitizeText(data.first_name, 80),
    last_name: sanitizeText(data.last_name, 80),
    username: sanitizeText(data.username, 80),
    photo_url: sanitizeText(data.photo_url, 500),
    phone_number: sanitizeText(data.phone_number, 40)
  };
}

export async function telegramApi(method, body) {
  if (!config.telegramBotToken) return { ok: false, skipped: true };
  const response = await fetch(`https://api.telegram.org/bot${config.telegramBotToken}/${method}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(12_000)
  });
  const data = await response.json().catch(() => ({ ok: false }));
  if (!response.ok || !data.ok) {
    throw Object.assign(new Error(data.description || 'Telegram API request failed.'), { code: 'TELEGRAM_API_ERROR', status: 502 });
  }
  return data;
}

export async function sendPhoneRequest(chatId, miniAppUrl = '') {
  const keyboard = [
    [{ text: '📱 Telefon Numaramı Doğrula', request_contact: true }]
  ];
  if (miniAppUrl) keyboard.push([{ text: '🎮 OnlyCoin Oyunu Aç', web_app: { url: miniAppUrl } }]);
  return telegramApi('sendMessage', {
    chat_id: chatId,
    text: 'OnlyCoin hesabınızı tamamlamak için telefon numaranızı yalnızca kendi onayınızla paylaşabilirsiniz. Telefon numaranız Telegram kullanıcı kimliğinizle eşleştirilir.',
    reply_markup: { keyboard, resize_keyboard: true, one_time_keyboard: true }
  });
}

export async function sendTelegramText(chatId, text, options = {}) {
  return telegramApi('sendMessage', { chat_id: chatId, text, parse_mode: options.parseMode || undefined, reply_markup: options.replyMarkup || undefined });
}
