<?php
namespace EasyChat\Library\Ai;

use EasyChat\Library\Messenger\MessengerLogger;
use EasyChat\Model\Message;
use EasyChat\Model\MessageContext;
use EasyChat\Model\MessengerItemContext;

class CommerceContextReadinessService {
    private const WAIT_DELAY_SECONDS = 15;
    private const MAX_WAIT_SECONDS = 45;
    private const MAX_WAITS = 3;

    private $registry;

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

    public function checkAiPayload(array $payload): array {
        $provider = $this->provider($payload['source_provider'] ?? '');
        $chat_id = (int)($payload['chat_id'] ?? 0);
        $message_id = (int)($payload['message_id'] ?? 0);
        if (!in_array($provider, ['avito', 'youla'], true) || $chat_id <= 0 || $message_id <= 0) {
            return ['ready' => true, 'reason' => 'not_commerce_message'];
        }

        $message = (new Message($this->registry))->getMessageById($message_id);
        if (!$message || (int)($message['chat_id'] ?? 0) !== $chat_id || (int)($message['author'] ?? 0) !== 1) {
            return ['ready' => true, 'reason' => 'not_customer_message'];
        }

        $readiness = $this->messageReadiness($provider, $message_id);
        if (!empty($readiness['ready'])) {
            $this->logReadiness('ai_context_readiness_ready', $chat_id, $message_id, array_merge($readiness, [
                'provider' => $provider,
            ]));
            return $readiness;
        }

        $next_payload = $this->nextPayload($payload);
        if (!$this->waitExpired($next_payload)) {
            $this->logReadiness('ai_context_readiness_wait', $chat_id, $message_id, [
                'provider' => $provider,
                'reason' => (string)($readiness['reason'] ?? 'commerce_context_not_ready'),
                'waits' => (int)($next_payload['commerce_context_waits'] ?? 0),
                'delay' => self::WAIT_DELAY_SECONDS,
            ]);
            return [
                'ready' => false,
                'reason' => (string)($readiness['reason'] ?? 'commerce_context_not_ready'),
                'delay' => self::WAIT_DELAY_SECONDS,
                'payload' => $next_payload,
            ];
        }

        if (($readiness['reason'] ?? '') === 'context_missing') {
            $this->ensureSafeGeneralContext($provider, $chat_id, $message_id, $message);
        }

        $this->logReadiness('ai_context_readiness_expired', $chat_id, $message_id, [
            'provider' => $provider,
            'reason' => (string)($readiness['reason'] ?? 'commerce_context_not_ready'),
            'waits' => (int)($next_payload['commerce_context_waits'] ?? 0),
        ]);

        return [
            'ready' => true,
            'reason' => 'commerce_context_wait_expired',
            'expired' => true,
        ];
    }

    private function messageReadiness(string $provider, int $message_id): array {
        $model = new MessageContext($this->registry);
        $item_context_type = $provider . '_item';

        $item = $model->getByMessageId($message_id, $item_context_type);
        if ($item) {
            if ($this->itemHasMinimumFacts($item) || $this->cacheHasMinimumFacts($item)) {
                return ['ready' => true, 'reason' => 'item_context_ready'];
            }
            return ['ready' => false, 'reason' => 'item_context_thin'];
        }

        if ($provider === 'avito') {
            $general = $model->getByMessageId($message_id, 'avito_general');
            if ($general) {
                return ['ready' => true, 'reason' => 'general_context_ready'];
            }
        }

        return ['ready' => false, 'reason' => 'context_missing'];
    }

    private function itemHasMinimumFacts(array $context): bool {
        if (trim((string)($context['item_id'] ?? '')) === '') {
            return false;
        }
        foreach (['title', 'url', 'price_string'] as $key) {
            if (trim((string)($context[$key] ?? '')) !== '') {
                return true;
            }
        }
        return false;
    }

    private function cacheHasMinimumFacts(array $context): bool {
        $channel_id = (int)($context['channel_id'] ?? 0);
        $item_id = trim((string)($context['item_id'] ?? ''));
        if ($channel_id <= 0 || $item_id === '') {
            return false;
        }

        $provider = $this->provider($context['provider'] ?? '');
        if (!in_array($provider, ['avito', 'youla'], true)) {
            return false;
        }

        $cached = (new MessengerItemContext($this->registry))->get($provider, $channel_id, $item_id);
        if (!$cached) {
            return false;
        }
        return $this->itemHasMinimumFacts($cached) || !empty($cached['details']);
    }

    private function nextPayload(array $payload): array {
        $now = time();
        $payload['commerce_context_wait_started_at'] = (int)($payload['commerce_context_wait_started_at'] ?? $now);
        $payload['commerce_context_waits'] = ((int)($payload['commerce_context_waits'] ?? 0)) + 1;
        return $payload;
    }

    private function waitExpired(array $payload): bool {
        $started_at = (int)($payload['commerce_context_wait_started_at'] ?? time());
        $waits = (int)($payload['commerce_context_waits'] ?? 0);
        return $waits >= self::MAX_WAITS || (time() - $started_at) >= self::MAX_WAIT_SECONDS;
    }

    private function ensureSafeGeneralContext(string $provider, int $chat_id, int $message_id, array $message): void {
        if ($provider !== 'avito') {
            return;
        }

        (new MessageContext($this->registry))->upsertAvitoGeneralContext([
            'channel_id' => (int)($message['source_channel_id'] ?? 0),
            'chat_id' => $chat_id,
            'message_id' => $message_id,
            'external_chat_id' => '',
            'external_user_id' => '',
            'external_message_id' => (string)($message['external_message_id'] ?? ''),
            'chat_type' => 'u2u',
            'title' => 'Контекст карточки Avito не получен',
            'url' => '',
            'snapshot' => [
                'context_kind' => 'general',
                'chat_type' => 'u2u',
                'title' => 'Контекст карточки Avito не получен',
            ],
        ]);
    }

    private function logReadiness(string $event, int $chat_id, int $message_id, array $context = []): void {
        try {
            $provider = $this->provider($context['provider'] ?? '');
            if (!in_array($provider, ['avito', 'youla'], true)) {
                $provider = 'avito';
            }

            (new MessengerLogger($this->registry, $provider))->info($event, array_merge([
                'provider' => $provider,
                'chat_id' => $chat_id,
                'message_id' => $message_id,
            ], array_filter([
                'reason' => isset($context['reason']) ? (string)$context['reason'] : null,
                'waits' => isset($context['waits']) ? (int)$context['waits'] : null,
                'delay' => isset($context['delay']) ? (int)$context['delay'] : null,
            ], static function ($value) {
                return $value !== null && $value !== '';
            })));
        } catch (\Throwable $e) {
             
        }
    }

    private function provider($provider): string {
        $provider = strtolower(preg_replace('/[^a-z0-9_\-]/i', '', (string)$provider));
        return $provider !== '' ? $provider : 'widget';
    }
}
