<?php
namespace EasyChat\Library\Messenger;

use EasyChat\Library\AppClock;
use EasyChat\Model\Messenger as MessengerModel;
use EasyChat\Model\Setting;

class VkCallbackRepairService {
    const JOB_TYPE = 'messenger_vk_callback_repair';

    private $registry;

    public function __construct($registry) {
        $this->registry = $registry;
    }

    public function repairByPayload(array $payload): array {
        $channel_id = (int)($payload['channel_id'] ?? 0);
        if ($channel_id <= 0) {
            return ['success' => false, 'error' => 'channel_id_required'];
        }

        $model_messenger = new MessengerModel($this->registry);
        $channel = $model_messenger->getChannelById($channel_id);
        if (!$channel || (string)($channel['provider'] ?? '') !== 'vk') {
            return ['success' => true, 'skipped' => 'channel_missing'];
        }
        if ((string)($channel['status'] ?? '') !== 'active') {
            return ['success' => true, 'skipped' => 'channel_inactive'];
        }

        $credentials = json_decode((string)($channel['credentials_json'] ?? ''), true);
        if (!is_array($credentials)) {
            $credentials = [];
        }

        $install_secret = (new Setting($this->registry))->get('chat_install_secret', '');
        $token = SecretBox::decrypt((string)($credentials['bot_token'] ?? ''), $install_secret);
        $group_id = preg_replace('/\D+/', '', (string)($credentials['vk_group_id'] ?? $channel['bot_user_id'] ?? ''));
        $server_id = preg_replace('/\D+/', '', (string)($credentials['callback_server_id'] ?? ''));
        $secret_key = SecretBox::decrypt((string)($credentials['secret_key'] ?? ''), $install_secret);
        $webhook_url = $this->webhookUrl($channel);

        if ($token === '' || $webhook_url === '') {
            $this->markRepairSkipped($model_messenger, $channel_id, 'vk_callback_repair_config_incomplete');
            return ['success' => true, 'skipped' => 'config_incomplete'];
        }

        if (!$this->isValidSecretKey($secret_key)) {
             
             
             
            $secret_key = 'vk' . bin2hex(random_bytes(20));
            $credentials['secret_key'] = SecretBox::encrypt($secret_key, $install_secret);
            $channel['credentials_json'] = json_encode($credentials, JSON_UNESCAPED_UNICODE);
        }

        $channel['webhook_url'] = $webhook_url;
        $provider = new VkProvider($this->registry);
        $sync = $provider->syncWebhook($channel, $token, $webhook_url, $secret_key);
        if (empty($sync['success'])) {
            $error = $this->shortError((string)($sync['error'] ?? 'vk_callback_repair_failed'));
            if (!empty($sync['rate_limited'])) {
                $model_messenger->updateChannel($channel_id, [
                    'last_error' => $error,
                ]);
                return [
                    'success' => false,
                    'rate_limited' => true,
                    'error' => $error,
                    'retry_after' => (int)($sync['retry_after'] ?? 300),
                ];
            }

            $model_messenger->updateChannel($channel_id, [
                'last_error' => $error,
            ]);
            return ['success' => false, 'error' => $error];
        }

        $bot = is_array($sync['bot'] ?? null) ? $sync['bot'] : [];
        $group_id = preg_replace('/\D+/', '', (string)($sync['group_id'] ?? $group_id));
        if ($group_id === '') {
            $group_id = preg_replace('/\D+/', '', (string)($bot['user_id'] ?? $channel['bot_user_id'] ?? ''));
        }
        $credentials['callback_server_id'] = (string)($sync['server_id'] ?? $server_id);
        $credentials['vk_group_id'] = $group_id;
        $credentials['api_version'] = VkProvider::API_VERSION;

        $model_messenger->updateChannel($channel_id, [
            'status' => 'active',
            'credentials_json' => json_encode($credentials, JSON_UNESCAPED_UNICODE),
            'webhook_url' => $webhook_url,
            'webhook_synced_at' => (new AppClock($this->registry))->nowSql(),
            'bot_user_id' => (string)($bot['user_id'] ?? $group_id),
            'bot_name' => (string)($bot['name'] ?? $channel['bot_name'] ?? ''),
            'bot_username' => (string)($bot['username'] ?? $channel['bot_username'] ?? ''),
            'last_error' => '',
        ]);

        return [
            'success' => true,
            'channel_id' => $channel_id,
            'server_id' => (string)($sync['server_id'] ?? $server_id),
        ];
    }

    private function webhookUrl(array $channel): string {
        $stored = trim((string)($channel['webhook_url'] ?? ''));
        if ($stored !== '') {
            return $stored;
        }

        if (!defined('HTTP_SERVER') || trim((string)HTTP_SERVER) === '' || trim((string)($channel['public_id'] ?? '')) === '') {
            return '';
        }

        return rtrim((string)HTTP_SERVER, '/') . '/index.php?route=messenger/webhook&provider=vk&id=' . urlencode((string)$channel['public_id']);
    }

    private function isValidSecretKey(string $secret): bool {
        $secret = trim($secret);
        return $secret !== '' && preg_match('/^[A-Za-z0-9]{1,50}$/', $secret) === 1;
    }

    private function markRepairSkipped(MessengerModel $model_messenger, int $channel_id, string $reason): void {
        $model_messenger->updateChannel($channel_id, [
            'last_error' => $this->shortError($reason),
        ]);
    }

    private function shortError(string $error): string {
        $error = trim($error);
        if ($error === '') {
            $error = 'vk_callback_repair_failed';
        }
        return function_exists('mb_substr') ? mb_substr($error, 0, 180, 'UTF-8') : substr($error, 0, 180);
    }
}
