import { Injectable } from '@nestjs/common';
import { createHmac, timingSafeEqual } from 'node:crypto';

@Injectable()
export class WebAppCryptoService {
  validateWebAppData(initData: string, botToken: string, maxAgeSeconds = 86_400) {
    if (!initData?.trim() || !botToken?.trim()) {
      return { valid: false as const, error: 'Пустые initData или botToken' };
    }

    const params = new URLSearchParams(initData);
    const receivedHash = params.get('hash');
    if (!receivedHash) {
      return { valid: false as const, error: 'Отсутствует hash в initData' };
    }

    const authDateRaw = params.get('auth_date');
    if (!authDateRaw) {
      return { valid: false as const, error: 'Отсутствует auth_date в initData' };
    }

    const authDate = Number(authDateRaw);
    if (!Number.isFinite(authDate)) {
      return { valid: false as const, error: 'Некорректный auth_date' };
    }

    const nowSeconds = Math.floor(Date.now() / 1000);
    if (nowSeconds - authDate > maxAgeSeconds) {
      return { valid: false as const, error: 'Срок действия initData истёк' };
    }

    const dataCheckString = [...params.entries()]
      .filter(([key]) => key !== 'hash')
      .sort(([left], [right]) => left.localeCompare(right))
      .map(([key, value]) => `${key}=${value}`)
      .join('\n');

    const secretKey = createHmac('sha256', 'WebAppData').update(botToken).digest();
    const calculatedHash = createHmac('sha256', secretKey).update(dataCheckString).digest('hex');

    const receivedBuffer = Buffer.from(receivedHash, 'hex');
    const calculatedBuffer = Buffer.from(calculatedHash, 'hex');
    if (receivedBuffer.length !== calculatedBuffer.length || !timingSafeEqual(receivedBuffer, calculatedBuffer)) {
      return { valid: false as const, error: 'Подпись initData не совпадает' };
    }

    const userRaw = params.get('user');
    return {
      valid: true as const,
      userJson: userRaw ?? undefined,
      authDate: authDateRaw
    };
  }
}
