<?php
namespace Bot\Services;

use Bot\Config;
use Bot\Database;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use PDO;
use Psr\Http\Message\ResponseInterface;

class KycService
{
    private Client $http;
    private array $config;
    private PDO $pdo;
    private string $apiKey;

    public function __construct(?Client $client = null)
    {
        $this->config = Config::get()->getValue('didit', []);
        $this->apiKey = (string) ($this->config['api_key'] ?? '');
        $baseUri = rtrim($this->config['api_base'] ?? 'https://verification.didit.me', '/') . '/';
        $this->http = $client ?? new Client([
            'base_uri' => $baseUri,
            'timeout'  => 10,
        ]);
        $this->pdo = Database::connection();
    }

    public function requiresKyc(float $amount): bool
    {
        $threshold = (float) Config::get()->getValue('kyc_required_threshold', 0);
        return $threshold > 0 && $amount >= $threshold;
    }

    /**
     * Create a Didit verification session and persist metadata on the user.
     *
     * @return array{session_id:string,url:string}
     */
    public function createSession(int $userId, array $userProfile): array
    {
        if ($this->apiKey === '' || empty($this->config['workflow_id'])) {
            throw new \RuntimeException('Didit API credentials missing. Configure DIDIT_* keys.');
        }

        $language = strtolower(substr((string) ($userProfile['language'] ?? 'en'), 0, 2));
        $metadata = array_filter([
            'user_id'      => $userId,
            'telegram_id'  => $userProfile['telegram_id'] ?? null,
            'username'     => $userProfile['username'] ?? null,
            'first_name'   => $userProfile['first_name'] ?? null,
            'last_name'    => $userProfile['last_name'] ?? null,
        ], static fn ($value) => $value !== null && $value !== '');

        $payload = [
            'workflow_id' => $this->config['workflow_id'],
            'vendor_data' => 'user-' . $userId,
        ];
        if ($metadata) {
            $payload['metadata'] = $metadata;
        }
        if ($language !== '') {
            $payload['language'] = $language;
        }
        if (!empty($this->config['callback_url'])) {
            $payload['callback'] = $this->config['callback_url'];
        }
        if (!empty($this->config['return_url'])) {
            $payload['return_url'] = $this->config['return_url'];
        }

        $response = $this->request('POST', 'v2/session/', ['json' => $payload]);
        $body = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
        if (!isset($body['session_id'], $body['url'])) {
            throw new \RuntimeException('Unexpected response from Didit.');
        }
        $stmt = $this->pdo->prepare(
            'UPDATE users SET kyc_session_id = ?, kyc_url = ?, kyc_status = ?, updated_at = NOW() WHERE id = ?'
        );
        $stmt->execute([$body['session_id'], $body['url'], 'pending', $userId]);
        return ['session_id' => $body['session_id'], 'url' => $body['url']];
    }

    public function markVerified(string $sessionId): void
    {
        $decision = $this->fetchSessionDecision($sessionId);
        $status = strtolower((string) ($decision['status'] ?? ''));
        $newStatus = match ($status) {
            'approved', 'verified', 'completed' => 'verified',
            'declined', 'rejected'              => 'rejected',
            'not started', 'in review', 'pending', 'processing' => 'pending',
            default                             => 'pending',
        };
        $stmt = $this->pdo->prepare('SELECT id FROM users WHERE kyc_session_id = ?');
        $stmt->execute([$sessionId]);
        $userId = $stmt->fetchColumn();
        if (!$userId) {
            return;
        }
        $update = $this->pdo->prepare('UPDATE users SET kyc_status = ?, updated_at = NOW() WHERE id = ?');
        $update->execute([$newStatus, $userId]);
        if ($newStatus === 'verified') {
            $referrals = new ReferralService();
            $referrals->handleKycVerified((int) $userId);
        }
    }

    public function fetchSessionDecision(string $sessionId): array
    {
        $endpoint = sprintf('v2/session/%s/decision/', rawurlencode($sessionId));
        $response = $this->request('GET', $endpoint);
        return json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
    }

    private function request(string $method, string $path, array $options = []): ResponseInterface
    {
        if ($this->apiKey === '') {
            throw new \RuntimeException('Didit API key not configured.');
        }
        $headers = array_merge([
            'x-api-key' => $this->apiKey,
            'Accept'    => 'application/json',
        ], $options['headers'] ?? []);
        $options['headers'] = $headers;
        try {
            return $this->http->request($method, ltrim($path, '/'), $options);
        } catch (GuzzleException $e) {
            throw new \RuntimeException('Didit API error: ' . $e->getMessage(), $e->getCode(), $e);
        }
    }
}
