<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\TelegramCustomer;
use Openguru\OpenCartFramework\Support\Arr;
use RuntimeException;

/**
 * Сервис для работы с Telegram-кастомерами
 *
 * @package App\Services
 */
class TelegramCustomerService
{
    private TelegramCustomer $telegramCustomerModel;

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

    /**
     * Сохранить или обновить Telegram-пользователя
     *
     * @param array $telegramUserData Данные пользователя из Telegram.WebApp.initDataUnsafe
     * @return void
     * @throws RuntimeException Если данные невалидны или не удалось сохранить
     */
    public function saveOrUpdate(array $telegramUserData): void
    {
        $telegramUserId = $this->extractTelegramUserId($telegramUserData);
        $telegramCustomerData = $this->prepareCustomerData($telegramUserData, $telegramUserId);

        $existingRecord = $this->telegramCustomerModel->findByTelegramUserId($telegramUserId);

        if ($existingRecord) {
            $this->telegramCustomerModel->updateByTelegramUserId($telegramUserId, $telegramCustomerData);
        } else {
            $this->telegramCustomerModel->create($telegramCustomerData);
        }
    }

    /**
     * Извлечь Telegram user ID из данных
     *
     * @param array $telegramUserData Данные пользователя
     * @return int Telegram user ID
     * @throws RuntimeException Если ID отсутствует или невалиден
     */
    private function extractTelegramUserId(array $telegramUserData): int
    {
        $telegramUserId = (int) Arr::get($telegramUserData, 'id');

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

        return $telegramUserId;
    }

    /**
     * Подготовить данные для сохранения в БД
     *
     * @param array $telegramUserData Исходные данные пользователя
     * @param int $telegramUserId Telegram user ID
     * @return array Подготовленные данные
     */
    private function prepareCustomerData(array $telegramUserData, int $telegramUserId): array
    {
        return [
            'telegram_user_id' => $telegramUserId,
            'username' => Arr::get($telegramUserData, 'username'),
            'first_name' => Arr::get($telegramUserData, 'first_name'),
            'last_name' => Arr::get($telegramUserData, 'last_name'),
            'language_code' => Arr::get($telegramUserData, 'language_code'),
            'is_premium' => $this->convertToInt(Arr::get($telegramUserData, 'is_premium', false)),
            'allows_write_to_pm' => $this->convertToInt(Arr::get($telegramUserData, 'allows_write_to_pm', false)),
            'photo_url' => Arr::get($telegramUserData, 'photo_url'),
            'last_seen_at' => date('Y-m-d H:i:s'),
        ];
    }

    /**
     * Конвертировать булево значение в int для БД
     *
     * @param mixed $value Значение для конвертации
     * @return int 1 или 0
     */
    private function convertToInt($value): int
    {
        return ($value === true || $value === 1 || $value === '1') ? 1 : 0;
    }
}
