<?php

declare(strict_types=1);

namespace Bastion\Handlers;

use App\Exceptions\TelegramCustomerNotFoundException;
use App\Exceptions\TelegramCustomerWriteNotAllowedException;
use App\Models\TelegramCustomer;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Telegram\TelegramService;
use Psr\Log\LoggerInterface;
use RuntimeException;

/**
 * Handler для отправки сообщений Telegram-пользователям из админ-панели
 *
 * @package Bastion\Handlers
 */
class SendMessageHandler
{
    private TelegramService $telegramService;
    private TelegramCustomer $telegramCustomerModel;
    private LoggerInterface $logger;

    public function __construct(
        TelegramService $telegramService,
        TelegramCustomer $telegramCustomerModel,
        LoggerInterface $logger
    ) {
        $this->telegramService = $telegramService;
        $this->telegramCustomerModel = $telegramCustomerModel;
        $this->logger = $logger;
    }

    /**
     * Отправить сообщение Telegram-пользователю
     *
     * @param Request $request HTTP запрос с id (ID записи в таблице) и message
     * @return JsonResponse JSON ответ с результатом операции
     * @throws TelegramCustomerNotFoundException Если пользователь не найден
     * @throws TelegramCustomerWriteNotAllowedException Если пользователь не разрешил писать в PM
     * @throws RuntimeException Если данные невалидны
     * @throws \Exception
     * @throws GuzzleException
     */
    public function sendMessage(Request $request): JsonResponse
    {
        $customerId = $this->extractCustomerId($request);
        $message = $this->extractMessage($request);

        // Находим запись по ID
        $customer = $this->telegramCustomerModel->findById($customerId);
        if (! $customer) {
            throw new TelegramCustomerNotFoundException($customerId);
        }

        $telegramUserId = (int) $customer['telegram_user_id'];

        // Проверяем, что пользователь разрешил писать ему в PM
        if (! $customer['allows_write_to_pm']) {
            throw new TelegramCustomerWriteNotAllowedException($telegramUserId);
        }

        // Отправляем сообщение (telegram_user_id используется как chat_id)
        // Используем пустую строку для parse_mode чтобы отправлять обычный текст
        $this->telegramService->sendMessage(
            $telegramUserId,
            $message,
        );

        $this->logger->info('Message sent to Telegram user', [
            'oc_customer_id' => $customerId,
            'telegram_user_id' => $telegramUserId,
            'message_length' => strlen($message),
        ]);

        return new JsonResponse([
            'success' => true,
            'message' => 'Message sent successfully',
        ]);
    }

    /**
     * Извлечь ID записи из запроса
     *
     * @param Request $request HTTP запрос
     * @return int ID записи в таблице telecart_customers
     * @throws RuntimeException Если ID отсутствует или невалиден
     */
    private function extractCustomerId(Request $request): int
    {
        $jsonData = $request->json();
        $customerId = isset($jsonData['id']) ? (int) $jsonData['id'] : 0;

        if ($customerId <= 0) {
            throw new RuntimeException('Customer ID is required and must be positive');
        }

        return $customerId;
    }

    /**
     * Извлечь сообщение из запроса
     *
     * @param Request $request HTTP запрос
     * @return string Текст сообщения
     * @throws RuntimeException Если сообщение отсутствует или пустое
     */
    private function extractMessage(Request $request): string
    {
        $jsonData = $request->json();
        $message = isset($jsonData['message']) ? trim($jsonData['message']) : '';

        if (empty($message)) {
            throw new RuntimeException('Message is required and cannot be empty');
        }

        return $message;
    }
}
