<?php
declare(strict_types=1);

final class Security
{
    private string $key;

    public function __construct(string $appKey)
    {
        if (strlen($appKey) < 32) {
            throw new RuntimeException('App key is too short.');
        }
        $this->key = hash('sha256', $appKey, true);
    }

    public function encrypt(string $plain): string
    {
        $iv = random_bytes(16);
        $cipher = openssl_encrypt($plain, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
        if ($cipher === false) {
            throw new RuntimeException('Encryption failed.');
        }
        $mac = hash_hmac('sha256', $iv . $cipher, $this->key, true);
        return base64_encode($iv . $mac . $cipher);
    }

    public function decrypt(string $payload): string
    {
        $raw = base64_decode($payload, true);
        if ($raw === false || strlen($raw) < 49) {
            throw new RuntimeException('Invalid encrypted payload.');
        }
        $iv = substr($raw, 0, 16);
        $mac = substr($raw, 16, 32);
        $cipher = substr($raw, 48);
        $calc = hash_hmac('sha256', $iv . $cipher, $this->key, true);
        if (!hash_equals($mac, $calc)) {
            throw new RuntimeException('Invalid encryption MAC.');
        }
        $plain = openssl_decrypt($cipher, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
        if ($plain === false) {
            throw new RuntimeException('Decryption failed.');
        }
        return $plain;
    }

    public static function randomSecret(int $bytes = 32): string
    {
        return bin2hex(random_bytes($bytes));
    }

    public static function verifyTelegramInitData(string $initData, string $botToken, int $maxAge = 86400): array
    {
        parse_str($initData, $data);
        if (!isset($data['hash'])) {
            throw new RuntimeException('داده ورود تلگرام hash ندارد.');
        }
        $hash = (string)$data['hash'];
        unset($data['hash']);
        ksort($data);
        $parts = [];
        foreach ($data as $k => $v) {
            $parts[] = $k . '=' . $v;
        }
        $checkString = implode("\n", $parts);
        $secretKey = hash_hmac('sha256', $botToken, 'WebAppData', true);
        $calc = hash_hmac('sha256', $checkString, $secretKey);
        if (!hash_equals($hash, $calc)) {
            throw new RuntimeException('ورود تلگرام معتبر نیست.');
        }
        if (isset($data['auth_date']) && (time() - (int)$data['auth_date']) > $maxAge) {
            throw new RuntimeException('ورود تلگرام منقضی شده است.');
        }
        $user = json_decode((string)($data['user'] ?? ''), true);
        if (!is_array($user) || empty($user['id'])) {
            throw new RuntimeException('اطلاعات کاربر تلگرام پیدا نشد.');
        }
        return $user;
    }
}
